Xunit: выполнить все «утверждения» в одном тестовом методе? - PullRequest
2 голосов
/ 04 декабря 2009

Можно ли попросить xUnit.net выполнить все, например? Assert.True() в одном методе испытаний? В основном в некоторых наших случаях использования / тестирования все утверждения логически принадлежат одному и тому же «объему» тестов, и я имею, например, как то так:

    [Fact(DisplayName = "Tr-MissImpl")]
    public void MissingImplementationTest()
    {
        // parse export.xml file
        var exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>(
                ExportXmlFile);

        // compare parsed results with expected ones
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_154163", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155763", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155931", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_157145", "E0032A"));

        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_A", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_C", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_D", "E0032A"));       
    }

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

Ответы [ 2 ]

8 голосов
/ 04 декабря 2009

Весь смысл AAA состоит в том, чтобы максимально упростить каждую часть и сохранить ее сфокусированность, чтобы читатели могли быстро понять тесты и легко выявить причину отказов.

У вас есть 7 различных Fact здесь, которые вместе составляют Theory. Таким образом, вы должны создать [Theory] с 7 наборами [InlineData], представляющими ожидания. См. http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html для примера.

Если повторное выполнение Arrange / Act является проблемой, то вы должны сделать это «приспособлением» (на языке тестовых шаблонов xUnit), выполнив это в конструкторе вашего тестового класса.

public class WithGenericClassDeserializer
{
    var exportXml;

    public WithGenericClassDeserializer()
    {
        // Or move this into the GivenExportXmlFile_ExpectedValueAtKeyShouldMatch
        exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>( ExportXmlFile );
    }

    [Theory( DisplayName = "Tr-MissImpl" )]
    [InlineData( "PERS_154163", "E0032A" )]
    [InlineData( "PERS_155763", "E0032A" )]
    [InlineData( "PERS_155931", "E0032A" )]
    [InlineData( "PERS_157145", "E0032A" )]
    [InlineData( "s_sw_ers_req_A", "E0032A" )]
    [InlineData( "s_sw_ers_req_C", "E0032A" )]
    [InlineData( "s_sw_ers_req_D", "E0032A" )]
    public void GivenExportXmlFile_ExpectedValueAtKeyShouldMatch( string key, string value )
    {
        Assert.True( exportXml.ContainsRequirementKeyWithError( key, value ) );
    }
}
0 голосов
/ 04 декабря 2009

Да, вы можете, но вы должны добавить дополнительный код в ваш тест. Каждый оператор Assert в xUnit выдает исключение, если завершение не удается. Так что в случае Assert.True он генерирует исключение TrueException. Так что вы могли бы сделать что-то вроде:

    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;

        passesValidation = PassesAssert(true == true);
        passesValidation = PassesAssert(false == true);
        passesValidation = PassesAssert(5 == 1);

        Assert.True(passesValidation);

    }

    private bool PassesAssert(bool expression)
    {
        try
        {
            Assert.True(expression);
            return true;
        }
        catch
        {
            return false;
        }
    }

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

       private StringBuilder resultMsg;
    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;
        resultMsg = new StringBuilder();

        passesValidation = PassesAssert(true == true, "True True test");
        passesValidation = PassesAssert(false == true, "False True test");
        passesValidation = PassesAssert(5 == 1, "5==1 Test");

        Assert.True(passesValidation, resultMsg.ToString());

    }

    private bool PassesAssert(bool expression, string message)
    {
        try
        {
            Assert.True(expression, message);
            return true;
        }
        catch (AssertException ex)
        {
            resultMsg.Append(ex.UserMessage);
            resultMsg.Append(Environment.NewLine);
            return false;
        }
    }

Конечно, это требует немного больше работы, но позволяет блокировать все ваши Активы вместе. Таким способом вы можете обернуть любой из ваших тестовых методов Assert. Таким образом, вы могли бы сказать, что вы расширяете xUnit для обеспечения безотказного процесса Assert.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ: Согласно комментариям, чтобы это работало, вам нужно будет использовать оператор &, так как последующие вызовы будут перезаписывать значение.

...