131

Basically I would like to tell MSTest to execute a bit of code before launching into a series of test runs, essentially what I would like to do is the same thing as sticking some code in Main().

The reason I would like to do this is that I would like to do some logging with log4net during my integration test runs. I cannot just use the log4net.Config.XmlConfigurator assembly attribute since by the time it reads it in my test assembly it has already called LoggerManager. The documentation recommends configuring log4net explicitly at the code entry point - but where is that in my tests?

I need to be able to run my tests in TestDriven.NET and MSTest runner.

Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • This works for me. Hope it works for you too. https://stackoverflow.com/a/74295793/1935980 – Mike Nov 02 '22 at 23:12

3 Answers3

172

FWIW, you can use the AssemblyInitialize attribute to run code before all unit tests in an assembly executes:

[TestClass]
public class SetupAssemblyInitializer
{
    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        // Initalization code goes here
    }
}

If you have more than one unit test assembly, I'm not aware of anything that encompasses more than one assembly.

As far as I'm aware, this is as close as you can get to a Main equivalent.

Note that the AssemblyInitialize-decorated method must be in a TestClass-decorated class which contains at least one TestMethod-decorated method, otherwise it will not be executed!

AakashM
  • 62,551
  • 17
  • 151
  • 186
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Nevermind, this does not work for my purposes. Our tests have to be runnable from MSTest and TestDriven.NET and the latter doesn't seem to support AssemblyInitialize – George Mauer Mar 04 '10 at 22:47
  • 1
    I had similar problem (only for MSTest) and worked fine. Thanks :) – Oscar Foley Oct 13 '11 at 10:12
  • 1
    For anyone else having issues with getting this working from both MsTest and TestDriven.NET, you can use a static flag to determine whether to run the code in ClassInitialize (this doesn't work in MsTest). – Carl Jan 25 '13 at 12:40
  • 8
    Note: The test engine runs a method that is marked with the AssemblyInitialize attribute only if that method is a member of a class that is marked with the TestClass attribute. – Jowen Mar 10 '15 at 08:37
  • 5
    @Jowen : The test engine runs a method that is marked with the AssemblyInitialize attribute only if that method is a member of a class that is marked with the TestClass attribute `and contains methods that are marked with the TestMethod attribute`. – oɔɯǝɹ Jun 01 '15 at 12:59
  • 4
    Method marked with AssemblyInitialize will run in Visual Studio 2015 Ultimate without other methods marked with TestMethod attributes. – Chris Jul 04 '17 at 07:42
  • [ClassInitialize] seems more appropriate in this case. – Sam Feb 18 '20 at 10:02
  • @Sam - [ClassInitialize] will run code once per class, but [AssemblyInitialize] will run once per assembly. So if you have 1298 test classes in your assembly and you want to run a piece of code once nstead of 1298 times, then you would want to use [AssemblyInitialize]. "More appropriate" really depends on what your intention is. – dcp Aug 25 '23 at 21:16
81

For completion, these are the "run code before" options for MSTest:

  • Use [AssemblyInitialize] to run code once per assembly, before any test in that assembly runs.
  • Use [ClassInitialize] to run code once per class, before any test in the class where the method is defined.
  • Use [TestInitialize] to run code before each and every test in the class where the method is defined.
Konamiman
  • 49,681
  • 17
  • 108
  • 138
  • 12
    The cleanup counterpart of these attributes is the Cleanup suffix (e.g. ClassCleanup) for tear-down operations – Yair Nevet Mar 24 '16 at 15:36
  • 3
    Note that `[ClassInitialize]` can't be just thrown in, and must be static and take exactly one parameter of type `TestContext` ([source](https://stackoverflow.com/a/11297661/3002584)). – OfirD Aug 08 '21 at 19:09
16

I see this in the MS Test header.

// Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext) { }

This would run before the tests in one class.

Sounds like you want to run something before all of the tests.

There is also the setup script option in the test run config.

Jess
  • 23,901
  • 21
  • 124
  • 145
Maestro1024
  • 3,173
  • 8
  • 35
  • 52
  • Unless I'm missing something, setup scripts don't help with running code in the test AppDomain. – George Mauer Mar 04 '10 at 22:48
  • 2
    It's probably me. I am not sure I follow you when you say "running code in the test AppDomain. ". I read your question as wanting to execute code before a series of tests, if it was something else that is different. "Setup scripts and cleanup scripts run before and after test runs, regardless of the types of tests that are contained in those test runs." http://msdn.microsoft.com/en-us/library/ms182480%28VS.80%29.aspx – Maestro1024 Mar 05 '10 at 15:25
  • 1
    Note that `[ClassInitialize]` can't be just thrown in, and must be static and take exactly one parameter of type `TestContext` ([source](https://stackoverflow.com/a/11297661/3002584)). – OfirD Aug 08 '21 at 19:09