Невозможно запустить тесты TestCaseSource, когда тестируемый тип переопределяет ToString

Во-первых, позвольте мне представить тестовую настройку на F# (используя FsUnit поверх NUnit):

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString()

[<TestFixture>]
type ``Simple Test Cases``() =     
    static member SimpleDataSource =
        [|
            [|{ A = 1; B = 2} ,3|]
        |]

    [<TestCaseSource("SimpleDataSource")>]
    member x.``SimpleTest`` (testData: SimpleRecord * int) =
        let data, expected = testData
        data.A + data.B
        |> should equal expected

Этот тест будет запущен и пройдет, как ожидалось. Однако изменение переопределения ToString для включения вызова Guid.ToString() предотвратит запуск теста:

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString() + Guid.NewGuid().ToString()

С указанным выше изменением тест по-прежнему отображается в обозревателе тестов, но не будет выполняться. Даже если щелкнуть его правой кнопкой мыши и выбрать «Выполнить выбранные тесты», тест не будет выполнен. Об ошибках сборки не сообщается.

Я также экспериментировал с использованием DateTime.ToString() вместо Guid.ToString(), но это также отказывается работать:

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString() + DateTime.Now.ToString()

Почему вызов Guid.ToString() или DateTime.ToString() в переопределении ToString для тестируемого типа приводит к тому, что тест не выполняется?


person Ifligus    schedule 14.08.2015    source источник
comment
Для меня это похоже на проблему с тестовым бегуном. Я могу воспроизвести его с помощью тестового адаптера NUnit для Visual Studio, но если я запускаю тесты с помощью nunit-console.exe, все работает нормально. Он также отлично работает с TestDriven.Net.   -  person Mark Seemann    schedule 14.08.2015
comment
Я полагаю, вы говорите о тестировщике ReSharper?   -  person Matthias    schedule 15.08.2015
comment
@MarkSeemann Вы правы! Я разместил объяснение и решение ниже.   -  person Ifligus    schedule 15.08.2015
comment
@Matthias Я использую обозреватель тестов Visual Studio 2013 с тестовым адаптером NUnit.   -  person Ifligus    schedule 15.08.2015


Ответы (1)


Чарли Пул объяснил основную причину:

Когда тесты запускаются с помощью консоли NUnit или средств выполнения графического интерфейса, они сначала загружаются (обнаруживаются), а затем выполняются. При запуске под адаптером тесты загружаются дважды, один раз в фазе обнаружения и еще раз в начале фазы выполнения. Это результат того, как работает тестовое окно VS: обнаружение и выполнение выполняются в отдельных процессах, созданных VS.

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

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

В вашем случае руководство генерируется дважды. Первый используется как часть имени теста, следовательно, этот тест исчезает на этапе выполнения.

Вот пример, демонстрирующий обходной путь:

type ProblemRecord = { A: int; B: int } 
                     override x.ToString() = Guid.NewGuid().ToString()

[<TestFixture>]
type ``Test Cases``() =     
    // Using TestCaseData and explicitly setting a name will resolve the problem
    member x.SolutionDataSource =
        [
            TestCaseData(({ A = 1; B = 2} : ProblemRecord), 3)
                .SetName("Workaround")
        ]

    // This test case will be run by Test Explorer
    [<TestCaseSource("SolutionDataSource")>]
    member x.``SolutionTest`` (data: ProblemRecord, expected: int) =
        data.A + data.B
        |> should equal expected
person Ifligus    schedule 15.08.2015