Как добавить поддержку атрибута теории xunit в Approvaltests

Когда я пытаюсь использовать одобрения с моим модульным тестом, украшенным [Theory] атрибут это говорит:

System.Exception: System.Exception : Approvals is not set up to use your test framework.
It currently supports [NUnit, MsTest, MbUnit, xUnit.net]
To add one use ApprovalTests.StackTraceParsers.StackTraceParser.AddParser() method to add implementation of ApprovalTests.StackTraceParsers.IStackTraceParser with support for your testing framework.
To learn how to implement one see http://blog.approvaltests.com/2012/01/creating-namers.html
   at ApprovalTests.StackTraceParsers.StackTraceParser.Parse(StackTrace stackTrace)
   at ApprovalTests.Namers.UnitTestFrameworkNamer..ctor()
   at ApprovalTests.Approvals.GetDefaultNamer()
   at ApprovalTests.Approvals.Verify(IApprovalWriter writer)
   at ApprovalTests.Approvals.Verify(Object text)

Похоже, это признает [Fact] только атрибуты. Я пытался перейти по ссылке из stacktrace, но нет ничего о том, как подключить ваш собственный namer / parser к одобрениям.

Есть ли точка входа, где я могу добавить свой собственный namer / parser? Само это кажется тривиальным, вопрос только в том, как его использовать:

 public class TheoryNamer : AttributeStackTraceParser
    {
        protected override string GetAttributeType()
        {
            return typeof(TheoryAttribute).FullName;
        }

        public override string ForTestingFramework
        {
            get { return "xUnit Extensions"; }
        }
    }

2 ответа

Решение

В этом ответе и вопросе есть пара частей.

  1. Как добавить
  2. Имя
  3. Работа с тестами на основе данных в тестах на одобрение

1) Как добавить

Добавление простое (если немного грубое) Упомянутый метод должен быть статическим, но тем не менее он работает.

Для добавления одного используйте метод ApprovalTests.StackTraceParsers.StackTraceParser.AddParser(), чтобы добавить реализацию ApprovalTests.StackTraceParsers.IStackTraceParser с поддержкой вашей инфраструктуры тестирования.

так что вам нужно сделать

new StackTraceParser().AddParser(new TheoryNamer());

Я прошу прощения за это, и он будет статичным в следующей версии (v.21)

2) Имя

Предполагается, что Namer генерирует уникальное имя для каждого утвержденного / полученного файла. Обычно это делается для имени метода, однако имя здесь не будет уникальным, так как теоретический тест будет основан на данных и, следовательно, будет иметь несколько вызовов одного и того же метода.

Naming:  classname.methodname(optional: .additionalInformation).received.extension

Таким образом, вам, вероятно, придется включить дополнительную информацию в метод, который он сам

public class StringTests1
{
    [Theory,
    InlineData("goodnight moon"),
    InlineData("hello world")]
    public void Contains(string input)
    {
        NamerFactory.AdditionalInformation = input;  // <- important
        Approvals.Verify(transform(input));
    }
} 

3) Работа с тестами на основе данных в тестах

Честно говоря, в большинстве случаев метод подхода, основанный на данных, в сертификационных тестах не является параметром в методах декораторов. Обычно это VerifyAll с лямбда-преобразованием. Например, приведенное выше может выглядеть так:

[Fact]
public void UpperCase()
{
    var inputs = new[]{"goodnight moon","hello world"};
    Approvals.VerifyAll(inputs, i => "{0} => {1}".FormatWith(i, i.ToUpperInvariant()));
}

Который создаст полученный файл:

goodnight moon => GOODNIGHT MOON
hello world => HELLO WORLD

Лучше наследовать класс TheoryNamer от XUnitStackTraceParser.
Работает отлично!
Я думаю, что было бы здорово добавить такой класс в пространство имен ApprovalTests.StackTraceParsers:)

public class XUnitTheoryStackTraceParser : XUnitStackTraceParser
{
    public const string TheoryAttribute = "Xunit.Extensions.TheoryAttribute";

    protected override string GetAttributeType()
    {
        return TheoryAttribute;
    }
}

public class ApproveTheoryTest
{
    static ApproveTheoryTest()
    {
        StackTraceParser.AddParser(new XUnitTheoryStackTraceParser());
    }

    [Theory]
    [UseReporter(typeof(DiffReporter))]
    [InlineData("file1.txt")]
    [InlineData("file2.txt")]
    public void approve_file(string fileName)
    {
        NamerFactory.AdditionalInformation = fileName;
        Approvals.Verify("sample text");
    }
}
Другие вопросы по тегам