12

I am writing some unit tests for the persistence layer of my C#.NET application. Before and after the tests of a test class execute, I want to do some cleaning up to erase possibly inserted dummy values, therefore, this cleaning up happens in methods marked with the attributes [ClassInitialize()] and [ClassCleanup()].

(I know that a better way would be to use an in-memory database, but it is not really doable so far as we depend on lots of stored procs....)

I would like to output some information about the results of the cleaning up, but I can not find a way to get the output in the test results with VISUAL Studio 2010.

This is what I am doing so far :

 ///... lots of stuff before ... //global for the test run private static TestContext context; //for each test private IRepository repo; #region Initialisation and cleanup /// <summary> /// Execute once before the test-suite /// </summary> [ClassInitialize()] public static void InitTestSuite(TestContext testContext) { context = testContext; removeTestDataFromDb(); } [ClassCleanup()] public static void CleanupTestSuite() { removeTestDataFromDb(); } private static void removeTestDataFromDb() { context.WriteLine("removeTestDataFromDb starting"); using (ISession session = NHibernateHelper.OpenSession()) { IDbConnection cn = session.Connection; IDbCommand cmd = cn.CreateCommand(); //remove anyt test data cmd.CommandText = @"DELETE FROM SomeTable WHERE somefield LIKE 'easyToFindTestData%Test'"; int res = cmd.ExecuteNonQuery(); context.WriteLine("removeTestDataFromDb done - affected {0} rows", res); } } [TestInitialize()] public void InitTest() { repo = new MyRepositoryImplementation(); } [TestCleanup()] public void CleanupTest() { //cleanup repo = null; } #endregion 

I'm trying to use context.WriteLine() ...

I also tried just using Console.WriteLine() with the same results.

How do you write to standard output in the ClassInitialize part and where can you access that output ?

0

3 Answers 3

20

The [ClassInitialize] and [ClassCleanup] run just once for all the tests in that class. You'd be better of using [TestInitialize] and [TestCleanUp] which run before and after each test. Also try wrapping the complete test in a database transaction. This way you can simply rollback the operation (by not committing the transaction) and your database stays in a consistent state (which is essential for trustworthy automated tests).

A trick I do for integration tests is to define a base class that all my integration test classes can inherit from. The base class ensures that each test is ran in a transaction and that this transaction is rolled back. Here is the code:

public abstract class IntegrationTestBase { private TransactionScope scope; [TestInitialize] public void TestInitialize() { scope = new TransactionScope(); } [TestCleanup] public void TestCleanup() { scope.Dispose(); } } 

Good luck.

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

6 Comments

Thanks for your advice Steven, but I would actually prefer to perform the clean up only once per class, actually. And as I am using NHibernate, I'm not too sure about the use of TransactionScope... I'll have a look at it, though. Anyway, this does not really answer my question about writing to output :-)
Please do not to cleanup once per class. Tests should run in isolation, and when you don't clean up test data per test, test get dependant on each other, which makes them untrustworthy. When you stop trusting your tests, they become useless. btw. TransactionScope works fine with NHibernate, because NHibernate just uses standard ADO.NET connections. Also, when you write to the console in [TestCleanup] you won’t have this problem, but please don’t write to the console, just rollback.
Thanks, I did not know about TransactionScope ... it looks like exactly what I need ! I am not sure I understand what happens under the hood, though ... It relies on MSDTC as far as I can see ... Thanks again !
The connections in System.Data check if a transaction scope is registered for the current thread. If that's the case, they use the same connection and transaction. TransactionScope can be promoted to a distributed transaction, that's where MSDTC is for. I personally find TransactionScope great for automated integration testing, but I think it is a design smell if it's used in production.
Yes, it is just perfect for testing database-related parts. That is an eay magic replacement for all the examples I've seen that involved in-memory databases and things like that... a bit too magic for production indeed :)
|
1

The trace output from a ClassInitialize and ClassCleanup appears in the result summary.

You can access it by doing the following

  1. Open the Test Results windw [ Test -> Windows -> Test Results ]
  2. There should be a link named "Test run completed" on the top left corner of the [Test Results] window.
  3. Click the clink
  4. It should open a window with the header "Result Summary" and it will show the debug trace created during ClassInitialize and ClassCleanup

1 Comment

Is this still supposed to work with VS2022?
0

You can see the Console output on each test if you double-click the test method in the Test Results pane. It is also present in the .trx xml results file.

In addition, if you specify the "Define DEBUG constant", you can use the System.Diagnostics.Debug.WriteLine("ClassInitialize Method invoked, yeah."); .. which will end up in the "Output" pane.

1 Comment

The ClassInitialize and ClassCleanup methods do not output to the output of individual tests. You can see TestInitialize and TestCleanup in their output though. Also, I cannot find the .trx files being generated by visual studio anywhere and I have to see a way to make them generate those files. Once I do though, I should be able to load them into the Test Results window that @hjb417 was talking about.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.