기본적으로 nunit 테스트는 알파벳순으로 실행됩니다. 실행 순서를 설정하는 방법을 아는 사람이 있습니까? 이에 대한 속성이 있습니까?
기본적으로 nunit 테스트는 알파벳순으로 실행됩니다. 실행 순서를 설정하는 방법을 아는 사람이 있습니까? 이에 대한 속성이 있습니까?
답변:
단위 테스트는 각각 독립적으로 실행될 수 있어야합니다. 이 기준을 충족하면 순서는 중요하지 않습니다.
그러나 특정 테스트를 먼저 실행하고 싶은 경우가 있습니다. 일반적인 예는 일부 테스트가 다른 테스트보다 오래 실행되는 지속적 통합 상황입니다. 우리는 데이터베이스를 사용하는 테스트보다 먼저 조롱을 사용하는 테스트를 실행할 수 있도록 category 속성을 사용합니다.
즉, 빠른 테스트를 시작할 때 이것을 넣으십시오.
[Category("QuickTests")]
특정 환경 조건에 의존하는 테스트가있는 경우 테스트 전후에 실행할 메서드를 표시 할 수 있는 TestFixtureSetUp 및 TestFixtureTearDown 속성을 고려하십시오 .
나는 대부분의 응답자들이 이것이 단위 테스트라고 가정했지만, 질문은 그것들이 있다고 명시하지 않았다는 점을 지적하고 싶습니다.
nUnit은 다양한 테스트 상황에 사용할 수있는 훌륭한 도구입니다. 테스트 순서를 제어하려는 적절한 이유를 알 수 있습니다.
이러한 상황에서 나는 실행 순서를 테스트 이름에 통합해야했습니다. 속성을 사용하여 실행 순서를 지정할 수 있으면 좋을 것입니다.
001_first_test
002_second_test
입니까?
NUnit 3.2.0은를 추가했습니다 OrderAttribute
.
https://github.com/nunit/docs/wiki/Order-Attribute
예:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
테스트가 특정 순서로 실행되기를 원한다고해서 테스트가 서로 의존한다는 의미는 아닙니다. 저는 현재 TDD 프로젝트를 진행하고 있으며, 좋은 TDDer가되어 모든 것을 조롱 / 스텁했습니다. 테스트 결과가 표시 되는 순서를 알파벳순 대신 주제별로 지정할 수 있다면 더 읽기 쉽습니다. 지금까지 내가 생각할 수있는 유일한 것은 클래스, 네임 스페이스 및 메서드의 클래스 앞에 a_ b_ c_를 추가하는 것입니다. (좋지 않음) [TestOrderAttribute] 속성이 좋을 것이라고 생각합니다. 프레임 워크가 엄격하게 따르는 것은 아니지만이를 달성 할 수있는 힌트입니다.
테스트가 질서에 의존하는지 여부에 관계없이 우리 중 일부는 모든 것을 질서 정연한 방식으로 제어하기를 원합니다.
단위 테스트는 일반적으로 복잡한 순서대로 생성됩니다. 그렇다면 복잡성이나 생성 된 순서대로 실행하면 안되는 이유는 무엇입니까?
개인적으로 테스트를 만든 순서대로 실행되는 것을보고 싶습니다. TDD에서 각 연속 테스트는 자연스럽게 더 복잡해지고 실행하는 데 더 많은 시간이 걸립니다. 더 간단한 테스트가 실패의 원인에 대한 더 나은 지표가 될 것이기 때문에 먼저 실패하는 것을보고 싶습니다.
그러나 특히 테스트가 다른 테스트에 대한 종속성이 없는지 테스트하려는 경우 무작위 순서로 실행하는 이점도 확인할 수 있습니다. "중지 될 때까지 무작위로 테스트 실행"옵션을 테스트 러너에 추가하는 것은 어떻습니까?
나는 상당히 복잡한 웹 사이트에서 Selenium으로 테스트하고 있으며 전체 테스트 스위트는 30 분 이상 실행할 수 있으며 아직 전체 애플리케이션을 다루지는 않습니다. 각 테스트에 대해 이전 양식을 모두 올바르게 작성해야한다면 전체 테스트에 약간의 시간이 아니라 많은 시간이 추가됩니다. 테스트를 실행하는 데 너무 많은 오버 헤드가 있으면 사람들은 필요한만큼 자주 실행하지 않을 것입니다.
그래서 나는 그것들을 순서대로 정리하고 이전 테스트에 의존하여 텍스트 상자를 완성했습니다. 전제 조건이 유효하지 않을 때 Assert.Ignore ()를 사용하지만 순서대로 실행해야합니다.
이전 답변이 정말 마음에 듭니다.
주문 범위를 설정하는 속성을 사용할 수 있도록 약간 변경했습니다.
namespace SmiMobile.Web.Selenium.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
public class OrderedTestAttribute : Attribute
{
public int Order { get; set; }
public OrderedTestAttribute(int order)
{
Order = order;
}
}
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt = new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[OrderedTest(0)]
public void Test0()
{
Console.WriteLine("This is test zero");
Assert.That(MyInt.I, Is.EqualTo(0));
}
[OrderedTest(2)]
public void ATest0()
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
[OrderedTest(1)]
public void BTest0()
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
[OrderedTest(3)]
public void AAA()
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
var assembly =Assembly.GetExecutingAssembly();
Dictionary<int, List<MethodInfo>> methods = assembly
.GetTypes()
.SelectMany(x => x.GetMethods())
.Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
.GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
foreach (var order in methods.Keys.OrderBy(x => x))
{
foreach (var methodInfo in methods[order])
{
MethodInfo info = methodInfo;
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
object classInstance = Activator.CreateInstance(info.DeclaringType, null);
info.Invoke(classInstance, null);
}
}).SetName(methodInfo.Name);
}
}
}
}
}
}
OrderedTest
NUnit 3에서는 더 이상 지원되지 않습니다.
나는 이것이 상대적으로 오래된 게시물이라는 것을 알고 있지만 여기에 테스트 이름을 어색하게 만들지 않고 테스트를 유지하는 또 다른 방법이 있습니다. TestCaseSource 특성을 사용하고 전달하는 개체에 대리자 (Action)가 있으면 순서를 완전히 제어 할 수있을뿐만 아니라 테스트 이름을 지정할 수도 있습니다.
문서에 따르면 테스트 소스에서 반환 된 컬렉션의 항목은 항상 나열된 순서대로 실행되기 때문에 작동합니다.
다음은 내일 발표 할 프레젠테이션의 데모입니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace NUnitTest
{
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt= new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
}).SetName(@"Test One");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
}).SetName(@"Test Two");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
}).SetName(@"Test Three");
}
}
}
}
TestCaseSource
주문 테스트를 실행하는 방법 으로을 사용하는 것은 천재적인 일입니다. 잘 했어. 이 접근 방식을 아래 방법과 함께 사용하고 사용하기 쉽도록 몇 가지 추가 수정 사항을 추가했습니다. 추가 정보는 내 답변의 링크를 참조하십시오.하지만 근본적인 아이디어는이 훌륭한 답변에서 나왔습니다!
TestCaseSource
가 정적이어야하므로 패턴을 사용할 수 없습니다. Bummer.
TestCaseSource
NUnit 3의 정적 개체 여야합니다. 그렇지 않으면 테스트가 실행되지 않습니다. 그리고 정적 개체 내에 동적 개체를 만들 수 없습니다. 그것이 v. 3에서 작동하지 않는 이유입니다.
저는 NUnit 프레임 워크를 사용하여 실행되는 C #으로 작성된 Selenium WebDriver 종단 간 UI 테스트 케이스를 사용하고 있습니다. (단위 케이스가 아닙니다)
다른 테스트에서는 일부 데이터를 전제 조건으로 추가해야하므로 이러한 UI 테스트는 실행 순서에 따라 달라집니다. (모든 테스트에서 단계를 수행하는 것은 불가능합니다)
이제 10 번째 테스트 케이스를 추가 한 후 NUnit이 다음 순서로 실행하려고합니다. Test_1 Test_10 Test_2 Test_3 ..
그래서 지금은 테스트 케이스 이름을 너무 알파벳순으로 만들어야한다고 생각하지만 실행 순서를 제어하는이 작은 기능을 NUnit에 추가하면 좋을 것입니다.
일반적으로 단위 테스트는 독립적이어야하지만 필요한 경우 다음과 같이 사전 순으로 메서드 이름을 지정할 수 있습니다.
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
아니면 할 수 있습니다 ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, t2_
후행 문자를 그리워 대신 또는 쉬운에 의존
테스트 주문 메커니즘을 사용하는 데에는 매우 좋은 이유가 있습니다. 내 테스트의 대부분은 설정 / 해체와 같은 좋은 방법을 사용합니다. 다른 것들은 방대한 양의 데이터 설정을 필요로하므로 다양한 기능을 테스트하는 데 사용할 수 있습니다. 지금까지 이러한 (Selenium Webdriver) 통합 테스트를 처리하기 위해 대규모 테스트를 사용했습니다. 하지만 https://github.com/nunit/docs/wiki/Order-Attribute 에 대한 위의 제안 된 게시물 이 많은 장점이 있다고 생각합니다 . 다음은 주문이 매우 중요한 이유에 대한 예입니다.
이 10 분의 대기 시간은 테스트 스위트의 속도를 늦 춥니 다. 여러 테스트에서 유사한 캐싱 지연을 곱하면 많은 시간이 소요됩니다. 테스트 순서 지정을 통해 테스트 스위트의 시작 부분에서 바로 "테스트"로 데이터 설정을 수행 할 수 있으며, 테스트 실행이 끝날 때 실행되는 캐시에 의존하는 테스트가 실행됩니다.
이 질문은 지금은 정말 오래되었지만 검색을 통해이 질문에 도달 할 수있는 사람들을 위해 user3275462 및 PvtVandals / Rico의 훌륭한 답변을 가져 와서 일부 업데이트와 함께 GitHub 저장소에 추가했습니다 . 관련 블로그 게시물 도 작성 했습니다. 더 많은 정보를 볼 수있는 몇 가지 추가 정보와 함께 을 .
이것이 여러분 모두에게 도움이되기를 바랍니다. 또한, 통합 테스트 또는 기타 종단 간 테스트를 실제 단위 테스트와 구별하기 위해 Category 속성을 자주 사용합니다. 다른 사람들은 단위 테스트에 순서 종속성이 없어야한다고 지적했지만 다른 테스트 유형은 종종 그렇기 때문에 원하는 테스트 범주 만 실행하고 이러한 엔드-투-엔드 테스트를 주문하는 좋은 방법을 제공합니다.
NUnit 커뮤니티가 아무 것도 생각해 내지 못한 것 같아서 제가 직접 이런 것을 만들어 보았습니다.
저는 현재 오픈 소스 라이브러리를 개발 중입니다. NUnit으로 테스트를 주문할 수 를 입니다. 테스트 픽스처를 주문하고 "주문 된 테스트 사양"을 주문할 수 있습니다.
라이브러리는 다음 기능을 제공합니다.
라이브러리는 실제로 MSTest가 .orderedtest
파일로 테스트 순서를 지정하는 방법에서 영감을 받았습니다 . 아래의 예를보십시오.
[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
protected override void DefineTestOrdering() {
TestFixture<Fixture1>();
OrderedTestSpecification<MyOtherOrderedTestFixture>();
TestFixture<Fixture2>();
TestFixture<Fixture3>();
}
protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}
을 사용하는 경우 [TestCase]
인수TestName
는 테스트의 이름을 제공합니다.
지정하지 않으면 제공된 메소드 이름과 인수를 기반으로 이름이 생성됩니다.
아래와 같이 테스트 실행 순서를 제어 할 수 있습니다.
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
여기에서는 메서드 이름을 사용했습니다. "ExpressionTest"
에서는 번호와 함께 접미사를 사용했습니다.
알파벳순으로 정렬 된 이름을 사용할 수 있습니다. TestCase 속성을 참조하십시오.
테스트 프레임 워크가 실행할 테스트를 선택하는 순서에 의존해서는 안됩니다.테스트는 격리되고 독립적이어야합니다. 그들은 그들을 위해 무대를 설정하거나 그 후에 정리하는 다른 테스트에 의존해서는 안됩니다. 또한 테스트 실행 순서에 관계없이 동일한 결과를 생성해야합니다 (주어진 SUT 스냅 샷에 대해).
나는 약간의 인터넷 검색을했다. 평소와 같이 일부 사람들은 기본 테스트 가능성 / 설계 문제를 해결하는 대신 은밀한 트릭에 의존했습니다.
참조 : 좋은 테스트의 특성
TestCaseSource
키 를 사용 하는 경우 override string ToString
방법은 작동 방식 :
TestCase 클래스가 있다고 가정하십시오.
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
그리고 TestCases 목록 :
private static IEnumerable<TestCase> TestSource()
{
return new List<TestCase>
{
new TestCase()
{
Name = "Test 1",
Input = 2,
Expected = 4
},
new TestCase()
{
Name = "Test 2",
Input = 4,
Expected = 16
},
new TestCase()
{
Name = "Test 3",
Input = 10,
Expected = 100
}
};
}
이제 Test 메서드와 함께 사용하고 어떤 일이 발생하는지 확인하십시오.
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
이것은 순서대로 테스트되지 않으며 출력은 다음과 같습니다.
따라서 override string ToString
다음과 같이 클래스에 추가 하면
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
결과가 변경되고 다음과 같은 테스트의 순서와 이름이 표시됩니다.
노트 :