Модульные тесты зарегистрированы (или выполненные) многократно

У меня есть этот простой тест:

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

log4net настраивается как это:

[TestFixtureSetUp]
public void SetUp()
{
    log4net.Config.BasicConfigurator.Configure();
}

Проблема, что, если я запускаю этот тест в nUnit однажды, я получаю вывод (как ожидалось):

1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method0

Но если я нажимаю ВЫПОЛНЕННЫЙ в nUnit.exe снова (или больше) я получаю следующее:

1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1
1742 [TestRunnerThread] DEBUG Tests.TestSomthing (null) - in test method1

И так далее (если я выполняю его 5 раз, я получу 5 строк повторения). Теперь, если я запускаю один только тот же тест от reSharper, вывод прекрасен и не повторяется. Однако, если я запускаю этот тест вдоль стороны 2 других теста в том же классе, вывод повторяется три раза.

Я полностью смущен. Что, черт возьми, продолжается здесь?

9
задан Michal Sznajder 10 August 2011 в 04:58
поделиться

1 ответ

Log4net заново инициализируется при каждом запуске теста, и каждый раз добавляется аппендер(ы). Я подозреваю, что ReSharper не демонстрирует такого поведения, поскольку он каждый раз запускает новый процесс (ReSharper test runner), в то время как NUnit GUI этого не делает.

В прошлом у меня были различные варианты этого, но уже довольно давно я использую "SetupFixture" для инициализации log4net (среди прочего).

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

    [TearDown]
    public void Teardown()
    {
        //Teardown stuff...
    }
}

Добавьте по одному из них на каждую тестовую сборку, и убедитесь, что класс не имеет пространства имен. Он будет выполняться один раз для всех ваших тестов, т.е. для всех тестов в сборке. Лично я располагаю один такой класс на уровне решения, а затем добавляю его в качестве ссылки в каждый тестовый проект.

Обновление

Пример выше следует вопросу и устанавливает базовую конфигурацию. В моей фактической SetUpFixture я инициализирую log4net из файла конфигурации log4net (который я снова храню на уровне решения и затем добавляю как ссылку во все тестовые проекты), например,

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

    [TearDown]
    public void Teardown()
    {
        //Teardown stuff...
    }
}

И пример класса типа 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();
    }
}
7
ответ дан 3 November 2019 в 04:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: