4

Background

We are slowly updating a very old application (based on "normal" SqlCommand queries and everything that comes with it) with some new code. To enhance stability and ease further development, we introduced NHibernate into the mix, along with good programming practices and what not.

So now, whenever a new module (not that the application is actually modular, but lets call it that) needs a large enough update, we break out all functionality into the "new" world of NHibernate and create a facade for the old code, so it keeps working.

Setup

I am creating Unit Tests for the facades. For this, I created a base class that all unit test classes are inheriting from. This class, on TestInitialize

  • creates the database schema using NHibernates "SchemaExport"
  • creates a "legacy" schema that consist of all tables that are not yet mapped by Nhibernate, but are needed by the facades to work

Every TestClass (inheriting from the one above) has its own DataSet.sql which is executed on TestInitialize, which

  • fills mapped Nhibernate tables with test specific data
  • fills the legacy tables with test specific data
  • fills a testExecutions table with input and expected output for each test run

The TestMethod of each TestClass then iterates over the testExecutions rows, creates the required objects (NHibernate), calls the facade it tests, and Asserts the returned data against what was defined in the testExecutions table.

Problem

The testing works fine, I get exactly the results I expect, but...

I have a big problem with this approach: Every test run visible in the test outputs is actually many many test executions. But from the outside, it just looks like a single test, even if the test itself actually runs the tested facade method many times over, with new data each time

I read about Data Driven Unit Tests and thought that it was literally exactly what I was already doing. So, instead of using my own things, I decided I should use that.

But the problem is: The TestContext.DataRow does obviously not know about NHibernate, so I don't actually get the objects required for testing, but a DataRow object with all data filled in the "old" way of Sql objects.

Is there a way to "teach" DataSource to return Nhibernate objects? Do I have to write my own DataSource attribute to accomplish this? How would that need to look?

Or is there another way

Is there a way to make my TestMethods to record the iteration over the testExecutions the same way a Data Driven test would do? So I don't have one Test, but the actual amount of tests run inside the method?

2 Answers 2

2
+50

Are you bound to MsTest? Consider using NUnit, which has extension points for exactly your scenario. Have a look at [TestCaseSource] attribute http://www.nunit.org/index.php?p=testCaseSource&r=2.5.9, which allows you to reference a method to get test data from. The data you source from there will appear as separate unit tests.

The method must be static, i.e. you have to work around passing the NHibernate session by means of using a static member, which you can set either in the class or test setup method.

Sign up to request clarification or add additional context in comments.

3 Comments

I tried using the methods you linked, but apparently it doesn't work in my case. The problem is that the TestCaseSource is executed before the SetUp methods, effectively querying the database before it even exists, see github... Using it statically will also cause problems because then I have to use two different NHibernate sessions for fetching data vs. manipulating that data in the actual Test... Maybe NUnit and MSTest are just not ready for truly data driven tests using data from external sources.
Yes, the static methods are not nice to use. You might still be able to hack the setup: You might use a static member to store the session factory, which you would have to create in the test cases method instead of the setup. In the test, you might then just create a new session from it. I know it's not how we would like to use it, but it might give a workaround.
Ill try to work on this some more, but at some point I think I will just settle with the fact that there is only "one" test per method, even if it encompasses more. Beats hacking the entire system...
0

Okay, I managed to get it working now, although I had to change quite a bit of code.

The root of my problem was, that I was using [TestInitialize] to create both the database structure (schema, tables, etc.) including the setup data AND the test-runs themselves.

MSTest and NUnit alike see things differently. The test runs need to exist BEFORE the tests are run. This means, that by the time [TestInitialize] (or [SetUp] respectively) are run, the [DataSource] (or [TestCaseSource]) is queried.

Obviously this didn't work in my case, because I only created the data for the test runs in the same methods that generate the table structure.

I reworked my test suites so that the test run data is contained in a separate file (Access DB), while the conext (schema, tables, initial data) is createdy new for each test method.

This would already work fine, if not for an annoying Visual Studio 2010 Bug that causes the [TestInitialize] and [TestCleanup] method to only run on the first iteration of a [DataSource]d test, so I had to put all of that in the normal constructors of the class...

Nonetheless, everything works as it should now an I can see the actual amount of tests run :-)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.