program tip

NUnit 테스트 실행 순서

radiobox 2020. 8. 6. 08:12
반응형

NUnit 테스트 실행 순서


기본적으로 nunit 테스트는 알파벳순으로 실행됩니다. 누구든지 실행 순서를 설정하는 방법을 알고 있습니까? 이것에 대한 속성이 있습니까?


단위 테스트는 각각 독립적으로 실행할 수 있어야합니다. 이들이이 기준을 만족하면 순서는 중요하지 않습니다.

그러나 특정 테스트를 먼저 실행하려는 경우가 있습니다. 일반적인 예는 일부 테스트가 다른 테스트보다 더 긴 연속 통합 상황입니다. 데이터베이스를 사용하는 테스트보다 조롱하는 테스트를 실행할 수 있도록 category 속성을 사용합니다.

즉, 빠른 테스트의 시작에 이것을 넣어

[Category("QuickTests")]

특정 환경 조건에 의존하는 테스트가있는 경우 TestFixtureSetUpTestFixtureTearDown 속성을 고려 하여 테스트 전후에 실행될 메소드를 표시 할 수 있습니다.


나는 대부분의 응답자들이 이것이 단위 테스트라고 가정했지만 질문은 그 테스트를 구체적으로 지정하지 않았다는 것을 지적하고 싶습니다.

nUnit은 다양한 테스트 상황에 사용할 수있는 훌륭한 도구입니다. 테스트 순서를 제어하려는 적절한 이유를 볼 수 있습니다.

그러한 상황에서 나는 테스트 이름에 런 순서를 통합해야했습니다. 속성을 사용하여 실행 순서를 지정할 수 있으면 좋을 것입니다.


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);
                    }
                }

            }
        }
    }
}

나는 이것이 비교적 오래된 게시물이라는 것을 알고 있지만 테스트 이름을 어색하게 만들지 않고 테스트를 유지하는 또 다른 방법이 있습니다. 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");
            }
        }
    }
}

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
        }

테스트 순서 메커니즘을 사용해야 할 이유는 매우 많습니다. 내 테스트의 대부분은 설정 / 티어 다운과 같은 모범 사례를 사용합니다. 다른 것들은 방대한 양의 데이터 설정을 요구하며, 그런 다음 다양한 기능을 테스트하는 데 사용될 수 있습니다. 지금까지 이러한 테스트 (Selenium Webdriver) 통합 테스트를 처리하기 위해 대규모 테스트를 사용했습니다. 그러나 https://github.com/nunit/docs/wiki/Order-Attribute 의 위의 제안 된 게시물 에는 많은 장점이 있다고 생각합니다 . 다음은 주문이 매우 가치있는 이유의 예입니다.

  • Selenium Webdriver를 사용하여 테스트를 실행하여 보고서 다운로드
  • 보고서 상태 (다운로드 가능 여부)는 10 분 동안 캐시됩니다.
  • That means, before every test I need to reset the report state and then wait up to 10 minutes before the state is confirmed to have changed, and then verify the report downloads correctly.
  • The reports cannot be generated in a practical / timely fashion through mocking or any other mechanism within the test framework due to their complexity.

This 10 minute wait time slows down the test suite. When you multiply similar caching delays across a multitude of tests, it consumes a lot of time. Ordering tests could allow data setup to be done as a "Test" right at the beginning of the test suite, with tests relying on the cache to bust being executed toward the end of the test run.


This question is really old now, but for people who may reach this from searching, I took the excellent answers from user3275462 and PvtVandals / Rico and added them to a GitHub repository along with some of my own updates. I also created an associated blog post with some additional info you can look at for more info.

Hope this is helpful for you all. Also, I often like to use the Category attribute to differentiate my integration tests or other end-to-end tests from my actual unit tests. Others have pointed out that unit tests should not have an order dependency, but other test types often do, so this provides a nice way to only run the category of tests you want and also order those end-to-end tests.


I'm suprised the NUnit community hasn't come up with anything, so I went to create something like this myself.

I'm currently developing an open-source library that allows you to order your tests with NUnit. You can order test fixtures and ordering "ordered test specifications" alike.

The library offers the following features:

  • Build complex test ordering hierarchies
  • Skip subsequent tests if an test in order fails
  • Order your test methods by dependency instead of integer order
  • Supports usage side-by-side with unordered tests. Unordered tests are executed first.

The library is actually inspired in how MSTest does test ordering with .orderedtest files. Please look at an example below.

[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
}

You should not depend on the order in which the test framework picks tests for execution. Tests should be isolated and independent. In that they should not depend on some other test setting the stage for them or cleaning up after them. They should also produce the same result irrespective of the order of the execution of tests (for a given snapshot of the SUT)

I did a bit of googling. As usual, some people have resorted to sneaky tricks (instead of solving the underlying testability/design issue

  • naming the tests in an alphabetically ordered manner such that tests appear in the order they 'need' to be executed. However NUnit may choose to change this behavior with a later release and then your tests would be hosed. Better check in the current NUnit binaries to Source Control.
  • VS (IMHO encouraging the wrong behavior with their 'agile tools') has something called as "Ordered tests" in their MS testing framework. I didn't waste any time reading up but it seems to be targeted towards the same audience

See Also: characteristics of a good test


If you are using [TestCase], the argument TestName provides a name for the test.

If not specified, a name is generated based on the method name and the arguments provided.

You can control the order of test execution as given below:

                    [Test]
            [TestCase("value1", TestName = "ExpressionTest_1")]
            [TestCase("value2", TestName = "ExpressionTest_2")]
            [TestCase("value3", TestName = "ExpressionTest_3")]
            public void ExpressionTest(string  v)
            {
                //do your stuff
            }

Here i used the method name "ExpressionTest" suffix with a number.

You can use any names ordered alphabetical see TestCase Attribute


In case of using TestCaseSource the key is to override string ToString method, How that works:

Assume you have TestCase class

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }
}

And a list of 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
        }
    };
}

Now lets use it with a Test method and see what happen:

[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
    var x = Power(testCase.Input);
    x.ShouldBe(testCase.Expected);
}

This will not test in order and the output will be like this:

enter image description here

So if we added override string ToString to our class like:

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

The result will change and we get the order and name of test like:

enter image description here

Note:

  1. This is just example to illustrate how to get name and order in test, the order is taken numerically/alphabetically so if you have more than ten test I suggest making Test 01, Test 02.... Test 10, Test 11 etc because if you make Test 1 and at some point Test 10 than the order will be Test 1, Test 10, Test 2 .. etc.
  2. The input and Expected can be any type, string, object or custom class.
  3. Beside order, the good thing here is that you see the test name which is more important.

참고URL : https://stackoverflow.com/questions/1078658/nunit-test-run-order

반응형