多次记录(或运行)单元测试

Ego*_*hin 9 c# resharper log4net nunit

我有这个简单的测试:

protected readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().ReflectedType);
private static int count = 0;
[Test]
public void TestConfiguredSuccessfully()
{
    logger.Debug("in test method" + count++);
}
Run Code Online (Sandbox Code Playgroud)

log4net设置如下:

[TestFixtureSetUp]
public void SetUp()
{
    log4net.Config.BasicConfigurator.Configure();
}
Run Code Online (Sandbox Code Playgroud)

问题是,如果我在nUnit中运行一次测试,我得到输出(如预期的那样):

1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method0
Run Code Online (Sandbox Code Playgroud)

但是,如果我再次在nUnit.exe中按RUN(或更多),我会得到以下内容:

1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1
1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1
Run Code Online (Sandbox Code Playgroud)

等等(如果我运行5次,我会得到5条重复的线条).现在,如果我从reSharper单独运行相同的测试,输出就可以了,不会重复.但是,如果我在同一个类中的另外两个测试中运行此测试,则输出重复三次.

我完全糊涂了.这到底是怎么回事?

Tim*_*oyd 7

每次测试运行时都会重新初始化Log4net,并且每次都会添加appender.我怀疑ReSharper没有表现出这种行为,因为它每次启动一个新进程(ReSharper测试运行器),而NUnit GUI没有.

我过去曾经有过各种各样的风格,但是很长一段时间以来我一直使用"SetupFixture"来初始化log4net(以及其他内容).

[SetUpFixture]
public class UnitTestSuiteSetupTeardown
{
    [SetUp]
    public void Setup()
    {
        log4net.Config.BasicConfigurator.Configure();
    }

    [TearDown]
    public void Teardown()
    {
        //Teardown stuff...
    }
}
Run Code Online (Sandbox Code Playgroud)

为每个测试程序集添加其中一个,并确保该类没有名称空间.对于所有测试,即组件中的所有测试,它将运行一次.我个人在解决方案级别拥有其中一个,然后将其添加为每个测试项目的链接.

更新

上面的示例遵循问题并设置基本配置.在我的实际SetUpFixture中,我从log4net配置文件初始化log4net(我再次在解决方案级别存储,然后添加为所有测试项目的链接),例如

[SetUpFixture]
public class UnitTestSuiteSetupTeardown
{
    [SetUp]
    public void Setup()
    {
        LogFactory.Configure();
    }

    [TearDown]
    public void Teardown()
    {
        //Teardown stuff...
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个示例LogFactory类型类.

public static class LogFactory
{
    public const string DefaultConfigFileName = "log4net.config";

    static ILog GetLogger(Type callingType)
    {
        return new Log4NetLogger(LogManager.GetLogger(callingType));
    }

    public static void Configure()
    {
        Type type = typeof(LogFactory);
        FileInfo assemblyDirectory = AssemblyInfo.GetCodeBaseDirectory(type);
        FileInfo configFile = new FileInfo(Path.Combine(assemblyDirectory.FullName,
            DefaultConfigFileName));
        XmlConfigurator.ConfigureAndWatch(configFile);
        log4net.ILog log = LogManager.GetLogger(type);
        log.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)