Подтвердить что ты не робот

Как запустить установочный код только один раз в тесте xUnit.net

Я пытаюсь настроить мои тесты с помощью Xunit. У меня есть требование удалить все изображения в начале запуска тестов, а затем каждый метод выполняет изменение размера изображения и сохраняет его копию в папке. Папка должна быть очищена только один раз, а затем каждый метод сохранит их собственное изображение в папке.

Когда я использую IUseFixture<T>, функция ClearVisualTestResultFolder все еще вызывается перед каждым тестом, так что я получаю только одно изображение в папке.

public class Fixture
{
    public void Setup()
    {
        ImageHelperTest.ClearVisualTestResultFolder();
    }
}

public class ImageHelperTest : IUseFixture<EngDev.Test.Fixture>
{
    public void SetFixture(EngDev.Test.Fixture data)
    {
        data.Setup();
    }

    public static void ClearVisualTestResultFolder()
    {
        // Logic to clear folder
    }
}

Если я поместил ClearVisualTestResultFolder в конструктор, он также вызывается один раз для каждого тестового метода. Мне нужно это просто запустить один раз, прежде чем все методы тестирования будут выполнены, как я могу достичь этого?

Если это имеет значение, я использую тестовый бегун ReSharper.

4b9b3361

Ответ 1

Следуя инструкциям в этом обсуждении xUnit, похоже, что вам нужно реализовать конструктор на Fixture, а также реализовать IDisposable. Здесь полный образец, который ведет себя так, как вы хотите:

using System;
using System.Diagnostics;
using Xunit;
using Xunit.Sdk;

namespace xUnitSample
{
    public class SomeFixture : IDisposable
    {
        public SomeFixture()
        {
            Console.WriteLine("SomeFixture ctor: This should only be run once");
        }

        public void SomeMethod()
        {
            Console.WriteLine("SomeFixture::SomeMethod()");
        }

        public void Dispose()
        {
            Console.WriteLine("SomeFixture: Disposing SomeFixture");
        }
    }

    public class TestSample : IUseFixture<SomeFixture>, IDisposable
    {
        public void SetFixture(SomeFixture data)
        {
            Console.WriteLine("TestSample::SetFixture(): Calling SomeMethod");
            data.SomeMethod();
        }

        public TestSample()
        {
            Console.WriteLine("This should be run once before every test " + DateTime.Now.Ticks);
        }

        [Fact]
        public void Test1()
        {
            Console.WriteLine("This is test one.");
        }

        [Fact]
        public void Test2()
        {
            Console.WriteLine("This is test two.");
        }

        public void Dispose()
        {
            Console.WriteLine("Disposing");
        }
    }
}

При запуске этого из консольного бегуна вы увидите следующий вывод:

D:\xUnit > xunit.console.clr4.exe test.dll/html foo.htm xUnit.net консольный тестовый бегун (64-разрядный .NET 4.0.30319.17929) Авторское право (C) 2007-11 Корпорация Microsoft.

xunit.dll: Версия 1.9.1.1600 Тестовая сборка: test.dll

SomeFixture ctor: это нужно запускать только один раз

Тесты завершены: 2 из 2

SomeFixture: Disposing SomeFixture

2 всего, 0 не удалось, 0 пропущено, заняло 0,686 секунды

Затем, когда вы вскрываете тестовый выходной файл foo.htm, вы увидите другой тестовый результат.

Ответ 2

Старый IUseFixture<T> интерфейс в xUnit.net v1.x был заменен двумя новыми интерфейсами: IClassFixture<T> и ICollectionFixture<T>. В Кроме того, механизм впрыскивания значений прибора в ваши тесты изменилось с атрибутов свойств на аргументы конструктора. Класс светильники создаются один раз и распределяются между всеми тестами в одном и том же класса (очень похоже на старое IUseFixture). Коллекционные светильники работают таким же образом, за исключением того, что один экземпляр является общим для всех тестов в той же коллекции тестов.

Ответ 3

IUseFixture<T>.SetFixture вызывается один раз для каждого теста. Сам Fixture создается только один раз.

Другими словами, вы не должны ничего делать в своем методе SetFixture, но вместо этого вы должны запускать его в конструкторе Fixture.

Для однократной очистки выполните IDisposable.Dispose в Fixture (этого не требуется)

Обратите внимание, что это плохая идея быть (даже потенциально) разделяющим состояние между тестами. Лучше всего использовать TemporaryDirectoryFixture как этот.