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

Доступ к NUnit Test Name в TestCaseSource

У меня есть серия тестов, в которых я хочу использовать те же данные тестовых данных для кучи разных тестов.

например:

[Test, TestCaseSource("TestData")] 
public void Test1(Foo foo)
{
    // test 1
}

[Test, TestCaseSource("TestData")] 
public void Test2(Foo foo)
{
    // test 2
}

private static IEnumerable TestData() 
{
   TestCaseData data; 

   data = new TestCaseData(new Foo("aaa"));
   yield return data; 

   data = new TestCaseData(new Foo("bbb"));
   yield return data; 
}

Это приводит к серии тестов, которые сообщают так:

Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo)  
Namespace.That.Is.Very.Long.TestClass.Test1(Namespace.That.Is.Very.Long.Foo)  
Namespace.That.Is.Very.Long.TestClass.Test2(Namespace.That.Is.Very.Long.Foo)  
Namespace.That.Is.Very.Long.TestClass.Test2(Namespace.That.Is.Very.Long.Foo)  

... который не имеет большого значения, если вы не знаете, что "foo" не удалось.

Если как предложено в этом вопросе SO, я задал имя следующим образом:

   data = new TestCaseData(new Foo("aaa"));
   data.SetName("foo=aaa");
   yield return data; 

... тогда все мои тесты выглядят так:

foo=aaa   
foo=bbb  
foo=aaa  
foo=bbb 

Итак, я пытаюсь выяснить, как получить текущее имя метода тестирования. Это выглядело бы как как описано в этом другом вопросе SO, через TestContext.

Однако, хотя TestContext.Current.Test существует, все свойства (например, Name) вызывают исключение NullReferenceException при попытке получить к ним доступ.

Есть ли другой способ достижения этой цели предоставления более полезной информации в имени теста?

4b9b3361

Ответ 1

Свойство TestName имеет поддержку в NUnit 3 для форматирования строк.

Здесь пример использования:

private static IEnumerable TestData()
{
    TestCaseData data;

    data = new TestCaseData(new Foo("aaa"))
                            .SetName("case 1 {m}");
    yield return data;

    data = new TestCaseData(new Foo("bbb"));
    yield return data;
}

Сгенерирует следующий вывод:

введите описание изображения здесь

Как вы можете видеть имена тестов, первый случай содержит пользовательский префикс + имя метода.

Используйте эту ссылку для получения дополнительной информации о возможности создания строк NUnit.

Для этого действия сохраняются 2 класса NUnitTestCaseBuilder (строка 83) и TestNameGenerator метод .GetDisplayName().

Ответ 2

После долгих поисковых запросов я нашел решение, которое было намного проще, чем те, которые были выше:

первый. В тестовом случае я добавил еще один параметр: string testName:

[Test, TestCaseSource("TestData")] 
public void Test1(string testName, Foo foo)
{
    // test 1
}

[Test, TestCaseSource("TestData")] 
public void Test2(String testName, Foo foo)
{
    // test 2
}

второй. в TestCaseData я добавил еще один параметр, который показывает уникальное свойство объекта Foo, например. имя

private static IEnumerable TestData() 
{
   TestCaseData data; 

   Foo data1 = new Foo("aaa");
   data = new TestCaseData(data1.name, data1);
   yield return data; 

   Foo data2 = new Foo("bbb");
   data = new TestCaseData(data2.name, data2);
   yield return data; 
}

В бегуне NUnit результат отображается следующим образом:

Namespace.That.Is.Very.Long.TestClass.Test1("aaa", Namespace.That.Is.Very.Long.Foo)
Namespace.That.Is.Very.Long.TestClass.Test1("bbb", Namespace.That.Is.Very.Long.Foo)  

Это делает тесты отдельными в окне вывода, в то время как я все еще могу видеть, какой именно тест выполняется.

Ответ 3

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

[Test, TestCaseSource("TestData_Test1")] 
public void Test1(Foo foo)
{
    // test 1
}

[Test, TestCaseSource("TestData_Test2")] 
public void Test2(Foo foo)
{
    // test 2
}


private static IEnumerable TestData_Test1() 
{
   return TestData_Base("Test1"); 
} 

private static IEnumerable TestData_Test2() 
{
   return TestData_Base("Test2"); 
} 

private static IEnumerable TestData_Base(string testName) 
{
   TestCaseData data; 

   data = new TestCaseData(new Foo("aaa"));
   data.SetName(string.Format("{0}(Foo=aaa)", testName)); 
   yield return data; 

   data = new TestCaseData(new Foo("bbb"));
   data.SetName(string.Format("{0}(Foo=bbb)", testName)); 
   yield return data; 
}

Это означает, что мои тесты теперь испускаются из NCrunch, TeamCity и т.д. как

Test1(Foo=aaa)
Test1(Foo=bbb)
Test2(Foo=aaa)
Test2(Foo=bbb) 

Это, по крайней мере, лучше, чем полностью бесполезное значение по умолчанию.

Ответ 4

Хорошо, если вам повезло использовать .NET 4.5, вы можете использовать атрибут [CallerMemberName] в последнем аргументе конструктора нового атрибута TestCaseSourceEx, расширяющего TestCaseSource, который даст вам имя метода тестирования внутри конструктора атрибутов,

Здесь рабочий пример:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestCaseSourceEx : TestCaseSourceAttribute
{
    public TestCaseSourceEx(Type sourceType, string sourceName, [CallerMemberName] string methodName = null)
        : base(sourceType, sourceName)
    {

    }
    public TestCaseSourceEx(string sourceName, [CallerMemberName] string methodName = null)
        : base(sourceName)
    {

    }
}

[TestFixture]
public class SampleTests
{
    public IEnumerable List = new[] { new string[] { "test-username", "test-password" } };

    [Test, TestCaseSourceEx("List")]
    public void SampleTests_LoginTest(string username, string password)
    {

    }
}

Ответ 5

Как насчет этого?

[TestCase("aaa")] 
[TestCase("bbb")] 
public void MainTest(string str)
{
  Assert.DoesNotThrow(()=> Test1(new Foo(str)));
  Assert.DoesNotThrow(()=> Test2(new Foo(str)));
}

public void Test1(Foo foo)
{
    // test 1
}

public void Test2(Foo foo)
{
    // test 2
}

UPD:

[TestCase("aaa")] 
[TestCase("bbb")] 
public void Test1(string str)
{
    var foo = new Foo(str);
    // rest of the test
}

[TestCase("aaa")] 
[TestCase("bbb")] 
public void Test2(string str)
{
    var foo = new Foo(str);
    // rest of the test
}