NUnit Test Run Order


110

โดยค่าเริ่มต้นการทดสอบแม่ชีจะรันตามตัวอักษร ไม่มีใครรู้วิธีกำหนดคำสั่งประหารชีวิต? มีแอตทริบิวต์สำหรับสิ่งนี้หรือไม่?


7
ทำไมคุณถึงต้องการทำเช่นนี้? ดูเหมือนว่าคุณต้องพึ่งพาคำสั่งเรียกใช้ซึ่งเป็นสิ่งที่ไม่ดี คุณต้องพิจารณาใหม่ว่าทำไมคุณถึงต้องการสิ่งนี้ การทดสอบหน่วยควรดำเนินการโดยแยกและเป็นอิสระจากผู้อื่น ดูเหมือนว่าคุณกำลังสร้างผู้สมัครกลิ่นทดสอบการทดสอบผิดปกติ
RichardOD

ดูเหมือนว่าจะซ้ำกัน แต่คุณสามารถดูคำตอบของฉันได้ที่นี่
Johnno Nolan

12
@RichardOD - ควร! = ต้อง และมันก็ไม่ใช่เหตุการณ์ที่ควรเพราะจริงๆแล้วการทดสอบการรวมเกือบทั้งหมดจะดำเนินการตามลำดับ - ถามทีม QA ของคุณว่าพวกเขาสุ่มลำดับการทดสอบหรือไม่
tymtam

4
ขณะนี้ฉันมีการทดสอบบางอย่างที่ดูเหมือนว่าจะมีความสำคัญแม้ว่าจะไม่ควรก็ตาม โดยส่วนตัวแล้วฉันต้องการวิธีสุ่มคำสั่งทดสอบโดยเฉพาะเพื่อช่วยให้มั่นใจได้ว่าการทดสอบของฉันไม่ขึ้นอยู่กับลำดับ แน่นอนสิ่งที่ฉันต้องการจริงๆคือนักวิ่งทดสอบที่จะทำการทดสอบทั้งหมดของฉันตามลำดับแบบสุ่มจนกว่าจะพบปัญหาหรือฉันบอกว่าหยุด ถ้าฉันวิ่งข้ามคืนและทุกอย่างยังคงเป็นสีเขียวในตอนเช้าฉันก็มั่นใจได้ว่าฉันได้กำจัดผลข้างเคียงสุดท้ายที่ไม่ได้ตั้งใจ
Mel

1
คำถามนี้จะมีความเกี่ยวข้องมากขึ้นหากคำถามได้รับการอัปเดตเพื่อระบุว่าเรากำลังพูดถึงการทดสอบการรวมที่นี่ ... เราทุกคนรู้กฎเกี่ยวกับการทดสอบหน่วยอย่างน้อยถ้าคุณได้อ่านรูปแบบการทดสอบ XUnit และติดตาม Uncle Bob เป็นต้น คุณทำ .. แต่เฟรมเวิร์กเช่น NUnit ก็มีประโยชน์มากสำหรับการทดสอบการรวมและทำงานได้อย่างรวดเร็วเช่นกัน .. และคุณไม่ต้องการให้สิ่งเหล่านั้นสุ่มโดยเฉพาะอย่างยิ่งเมื่อมีการตั้งค่าฐานข้อมูลที่มีราคาแพงเข้ามาเกี่ยวข้อง ..
nrjohnstone

คำตอบ:


51

การทดสอบหน่วยของคุณควรสามารถดำเนินการได้อย่างอิสระและเป็นเอกเทศ หากตรงตามเกณฑ์นี้คำสั่งก็ไม่สำคัญ

มีบางครั้งที่คุณจะต้องทำการทดสอบก่อน ตัวอย่างทั่วไปคือในสถานการณ์การผสานรวมแบบต่อเนื่องซึ่งการทดสอบบางอย่างทำงานนานกว่าการทดสอบอื่น ๆ เราใช้แอตทริบิวต์หมวดหมู่เพื่อให้เราสามารถเรียกใช้การทดสอบซึ่งใช้การเยาะเย้ยก่อนการทดสอบที่ใช้ฐานข้อมูล

กล่าวคือวางสิ่งนี้เมื่อเริ่มการทดสอบอย่างรวดเร็วของคุณ

[Category("QuickTests")]

ที่คุณมีการทดสอบซึ่งจะขึ้นอยู่กับสภาพแวดล้อมบางอย่างพิจารณาTestFixtureSetUpและTestFixtureTearDownคุณลักษณะที่ช่วยให้คุณวิธีการทำเครื่องหมายที่จะดำเนินการก่อนและหลังการทดสอบของคุณ


2
@ Chris ผมมักจะไม่ใช้แอตทริบิวต์เหล่านี้เป็นบล็อกที่น่าสนใจหลังjamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html ประเด็นที่ดีเกี่ยวกับการทดสอบหมวดหมู่แม้ว่า
RichardOD

29
อีกตัวอย่างหนึ่งของการทดสอบตามลำดับคือเมื่อคุณต้องการใช้กรอบแม่ชีของคุณเพื่อเรียกใช้การทดสอบการรวม ...
Byron Ross

1
@ByronRoss: ฉันมักจะทำการทดสอบให้ใหญ่ขึ้นเมื่อฉันทำเช่นนั้นและพึ่งพาการทดสอบหน่วยที่มีอยู่ให้มากที่สุดเพื่อที่ฉันจะได้เขียนแบบทดสอบน้อยลง จากนั้นการวิ่งเต็มแต่ละครั้งจะล้มเหลวแยกกัน ฉันยังพยายามออกแบบข้อมูลเพื่อให้สามารถใช้งานแยกจากข้อมูลที่มีอยู่ได้แทนที่จะขึ้นอยู่กับข้อมูลที่มีอยู่
Merlyn Morgan-Graham

1
หากคุณไม่ทำการทดสอบแบบสุ่มคุณจะตรวจสอบได้อย่างไรว่าการทดสอบนั้นใช้งานได้จริงเมื่อหมดคำสั่ง สิ่งที่คุณกำลังพูดนั้นคล้ายคลึงกับการพูดว่า "หากซอฟต์แวร์ของคุณไม่มีข้อบกพร่องการทดสอบก็ไม่จำเป็น"
jforberg

@jforberg: หากคุณมีความล้มเหลวที่เกิดขึ้นแบบสุ่มคุณจะพูดอย่างไรเมื่อแก้ไขแล้ว?
NeedHack

176

ฉันแค่ต้องการชี้ให้เห็นว่าในขณะที่ผู้ตอบส่วนใหญ่คิดว่าเป็นการทดสอบหน่วย แต่คำถามไม่ได้ระบุว่าเป็น

nUnit เป็นเครื่องมือที่ยอดเยี่ยมที่สามารถใช้ได้กับสถานการณ์การทดสอบที่หลากหลาย ฉันเห็นเหตุผลที่เหมาะสมที่ต้องการควบคุมคำสั่งทดสอบ

ในสถานการณ์เหล่านั้นฉันต้องใช้การรวมลำดับการทำงานเข้ากับชื่อการทดสอบ จะเป็นการดีที่สามารถระบุลำดับการรันโดยใช้แอตทริบิวต์


คุณหมายถึงคุณเรียกว่าการทดสอบของคุณ001_first_test 002_second_testเป็นต้น?
ashes999

ใช่ถูกต้องแม้ว่าโดยปกติฉันจะใช้รูปแบบที่ช่วยให้ฉันแทรกการทดสอบได้อย่างง่ายดายหากจำเป็นดังนั้นอาจเป็น 010_first_test, 020_second_test เป็นต้น
Les

84
ขอขอบคุณสำหรับคำตอบที่มีเหตุผลเดียวที่นี่ นี่เป็นคำถามที่เฉพาะเจาะจง แต่คำตอบเกี่ยวกับการอวดดียังไม่ชัดเจนกำลังได้รับการโหวต ใช่เราทุกคนรู้ว่าการทดสอบหน่วยการเรียนรู้ควรเป็นอย่างไรนั่นไม่ใช่คำถาม
Egor Pavlikhin

1
คุณไม่ควรพึ่งพาลำดับการทำงานที่เป็นตัวอักษร นักวิ่งทดสอบหลายคนทำการทดสอบของคุณพร้อมกันในเธรดหรือกระบวนการต่างๆมากมายและไม่จำเป็นต้องเรียงตามลำดับตัวอักษร ตัวอย่างเช่น NCrunch จะจัดลำดับความสำคัญของการทดสอบตามรหัสที่คุณเปลี่ยน (การทดสอบที่ได้รับผลกระทบ) จากนั้นพิจารณาว่าจะล้มเหลวในครั้งที่แล้วหรือไม่จากนั้นจะพิจารณาว่าจะทำงานเร็วหรือช้า หากคุณต้องการคำสั่งที่กำหนดไว้เพียงแค่สร้าง meta-runner สำหรับการทดสอบเหล่านั้นและแยกออกจากการวิ่งปกติ
Abel

3
อีกเหตุผลที่ดีในการระบุคำสั่งซื้อคือการตรวจจับปัญหาบางอย่างก่อนก่อนที่จะดำเนินการต่อกับชุดทดสอบที่เหลือ กล่าวอีกนัยหนึ่งคือหากการทดสอบสร้างผู้ใช้ของฉันล้มเหลวฉันไม่ต้องการให้ทุกอย่างทำงานก่อนที่จะพบผลลัพธ์นี้ ในการทดสอบอื่น ๆ ของฉันฉันอาจล้อเลียนผู้ใช้ แต่สิ่งสำคัญสำหรับฉันคือการทดสอบครั้งแรกที่ล้มเหลวโดยเฉพาะอย่างยิ่งเมื่อชุดทดสอบมีขนาดใหญ่
Bron Davies

125

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() { ... }
}

5
Thanx ตรงไปตรงมาถึงสิ่งที่ฉันกำลังมองหา - และไม่มีการพูดคุยทำไมมันดีหรือไม่ดี :)
aknoepfel

1
จากนั้นจึงทำให้เป็นจำนวนเต็มแทนที่จะเป็นทศนิยมดังนั้นหากต้องแทรกการทดสอบการทดสอบทั้งหมดจะต้องกำหนดหมายเลขใหม่
epitka

คุณสามารถเริ่มต้นด้วยตัวเลขที่มีขนาดใหญ่มากเช่นล้านหรืออะไรก็ได้หากคุณต้องการแนะนำรายการกลางด้วยวิธีนั้นเพียงแค่พิมพ์มากขึ้น Imo ควรมีวิธีที่ง่ายกว่าในการสั่งซื้อสิ่งต่างๆมากกว่าการใช้ตัวเลขสำหรับลำดับความสำคัญเช่นแผนผังการพึ่งพาวิธีการ แต่แต่ละวิธีก็มีข้อได้เปรียบ / ข้อดีของตัวเอง
Răzvan Flavius ​​Panda

9
คำตอบที่ดี แต่ระวังการทดสอบสถานะเอกสารอย่ารอให้การทดสอบก่อนเสร็จสิ้น
ROX

ที่น่าสนใจคือจากประสบการณ์ของฉันถ้าเราเพิ่มแอตทริบิวต์การทดสอบและการสั่งซื้อแยกกันจะไม่มีการรับประกันการสั่งซื้อการทดสอบ
AT

22

การต้องการให้การทดสอบทำงานตามลำดับที่เฉพาะเจาะจงไม่ได้หมายความว่าการทดสอบจะขึ้นอยู่กับกันและกัน - ฉันกำลังทำงานในโครงการ TDD ในขณะนี้และเป็น TDDer ที่ดีที่ฉันได้เยาะเย้ย / ขีดฆ่าทุกอย่าง แต่มันจะทำให้ มันอ่านง่ายขึ้นถ้าฉันสามารถระบุลำดับที่จะแสดงผลการทดสอบ- ตามหัวข้อแทนที่จะเป็นตัวอักษร จนถึงตอนนี้สิ่งเดียวที่ฉันคิดได้คือการเพิ่ม a_ b_ c_ ไปยังคลาสของคลาสเนมสเปซและวิธีการ (ไม่ดี) ฉันคิดว่าแอตทริบิวต์ [TestOrderAttribute] น่าจะดีไม่ใช่ตามกรอบอย่างเข้มงวด แต่เป็นคำใบ้เพื่อให้เราบรรลุเป้าหมายนี้


10

ไม่ว่าการทดสอบจะขึ้นอยู่กับลำดับหรือไม่ก็ตาม ... พวกเราบางคนต้องการควบคุมทุกสิ่งอย่างเป็นระเบียบ

การทดสอบหน่วยมักจะสร้างขึ้นตามลำดับความซับซ้อน เหตุใดจึงไม่ควรเรียกใช้ตามลำดับความซับซ้อนหรือลำดับที่สร้างขึ้น

โดยส่วนตัวแล้วฉันชอบที่จะเห็นการทดสอบดำเนินไปตามลำดับที่ฉันสร้างขึ้น ใน TDD การทดสอบต่อเนื่องแต่ละครั้งจะมีความซับซ้อนมากขึ้นและต้องใช้เวลามากขึ้นในการดำเนินการ ฉันอยากจะเห็นว่าการทดสอบที่ง่ายกว่านั้นล้มเหลวก่อนเพราะมันจะเป็นตัวบ่งชี้ที่ดีกว่าว่าสาเหตุของความล้มเหลว

แต่ฉันยังสามารถเห็นประโยชน์ของการเรียกใช้แบบสุ่มโดยเฉพาะอย่างยิ่งหากคุณต้องการทดสอบว่าการทดสอบของคุณไม่มีการพึ่งพาการทดสอบอื่น ๆ แล้วการเพิ่มตัวเลือกในการทดสอบนักวิ่งเป็น "Run Tests Randomly until Stopped" เป็นอย่างไร?


9

ฉันกำลังทดสอบกับ Selenium บนเว็บไซต์ที่ค่อนข้างซับซ้อนและชุดการทดสอบทั้งหมดสามารถใช้งานได้นานกว่าครึ่งชั่วโมงและฉันยังไม่ครอบคลุมแอปพลิเคชันทั้งหมด หากฉันต้องตรวจสอบให้แน่ใจว่ากรอกแบบฟอร์มก่อนหน้านี้ทั้งหมดอย่างถูกต้องสำหรับการทดสอบแต่ละครั้งสิ่งนี้จะเพิ่มเวลาให้กับการทดสอบโดยรวมไม่ใช่เพียงเล็กน้อย หากมีค่าใช้จ่ายในการดำเนินการทดสอบมากเกินไปผู้คนจะไม่เรียกใช้บ่อยเท่าที่ควร

ดังนั้นฉันจึงเรียงลำดับและขึ้นอยู่กับการทดสอบก่อนหน้านี้ว่ามีกล่องข้อความและเสร็จสมบูรณ์แล้ว ฉันใช้ Assert.Ignore () เมื่อเงื่อนไขเบื้องต้นไม่ถูกต้อง แต่ฉันจำเป็นต้องให้เงื่อนไขเหล่านั้นทำงานตามลำดับ


1
ทั้งหมด. ฉันอยู่ในเรือลำเดียวกันที่นี่
Sleeper Smith

ฉันด้วย! ว่าทำไมฉันถึงถามคำถามนี้!
Niklas Wulff

@NiklasRingdahl ถ้าคุณใช้ Visual Studio กับแม่ชีแม่ชีถ่ายโอนข้อมูลและใช้การทดสอบ MS จากนั้นคุณสามารถใช้ไฟล์คำสั่งการทดสอบของ Visual Studio เพื่อจัดเรียงกรณีทดสอบตามลำดับที่คุณต้องการให้ดำเนินการ
Rahul Lodha

@RahulLodha ขอบคุณ! ฉันจะตรวจสอบว่า
Niklas Wulff

9

ฉันชอบคำตอบก่อนหน้านี้มาก

ฉันเปลี่ยนแปลงเล็กน้อยเพื่อให้สามารถใช้แอตทริบิวต์เพื่อกำหนดช่วงการสั่งซื้อ:

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

            }
        }
    }
}

ฉันคิดว่าแนวทางนี้ดีมาก โปรดทราบว่ารหัสการสะท้อนจะดึงวิธีการทั้งหมดด้วยแอตทริบิวต์ดังนั้นหากคุณกำลังพยายามเรียกใช้ฟิกซ์เจอร์ทดสอบเฉพาะคุณอาจประหลาดใจที่พบว่ามันทำงานได้มากกว่าที่คุณคิด คุณสามารถแก้ไขแบบสอบถาม LINQ ได้อย่างง่ายดายหากนี่ไม่ใช่พฤติกรรมที่ต้องการ ดูลิงก์ในคำตอบของฉันสำหรับข้อมูลเพิ่มเติม
Chrispy

OrderedTestไม่รองรับใน NUnit 3 อีกต่อไป
Conrad

7

ฉันรู้ว่านี่เป็นโพสต์ที่ค่อนข้างเก่า แต่นี่เป็นอีกวิธีหนึ่งในการรักษาการทดสอบของคุณให้เป็นระเบียบโดยที่ไม่ทำให้ชื่อการทดสอบน่าอึดอัด ด้วยการใช้แอตทริบิวต์ 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");
            }
        }
    }
}

ฉันใช้รูปแบบนี้สำหรับการทดสอบการรวมแบบขนานซึ่งจะใช้เวลานานเกินไปในการรันแบบเชิงเส้น การทดสอบทั้งหมดอยู่ในประเภทเดียวดังนั้นฉันจึงใช้ Action <T in> และทุก Action จะมีคีย์ที่ระบุว่า "ShouldBeFoo" คืออะไร ด้วยวิธีนี้สิ่งที่ทดสอบจะปรากฏในชื่อการทดสอบและ TestCaseSource สามารถกรองเพื่อให้การทดสอบประเภทต่างๆถูกจัดกลุ่มเข้าด้วยกัน แดกดันฉันไม่สนใจคำสั่งดำเนินการ แต่ยอมรับว่ามันใช้ได้
Novaterata

การใช้TestCaseSourceเป็นวิธีเรียกใช้การทดสอบตามลำดับถือเป็นความอัจฉริยะ ทำได้ดี. ฉันได้ใช้แนวทางนี้ร่วมกับแนวทางด้านล่างและได้เพิ่มการปรับเปลี่ยนเพิ่มเติมเล็กน้อยเพื่อให้ใช้งานได้ง่ายขึ้น ดูลิงก์ในคำตอบของฉันสำหรับข้อมูลเพิ่มเติม แต่แนวคิดพื้นฐานมาจากคำตอบที่ยอดเยี่ยมนี้!
Chrispy

น่าเศร้าด้วย NUnit 3 แหล่งที่มาของTestCaseSourceต้องเป็นแบบคงที่ซึ่งขัดขวางการใช้รูปแบบ แย่จัง.
Conrad

@ คอนราด. ฉันไม่เห็นความแตกต่างที่ทำให้เมธอดคงที่หรือไม่ทำ การทดสอบยังคงกลับมาตามลำดับไม่ว่าจะด้วยวิธีใดก็ตาม
Dave Bush

ไม่ใช่วิธีการที่ต้องเป็นแบบคงที่ - แหล่งที่มา (ตัวแปรหรือคุณสมบัติ) ของTestCaseSourceต้องเป็นวัตถุคงที่ใน NUnit 3 ไม่เช่นนั้นการทดสอบจะไม่ดำเนินการ และคุณไม่สามารถสร้างวัตถุแบบไดนามิกภายในวัตถุคงที่ นั่นเป็นเหตุผลที่มันใช้ไม่ได้ใน
Conrad

5

ฉันกำลังทำงานกับกรณีทดสอบ UI แบบ end-to-end ของ Selenium WebDriver ที่เขียนด้วยภาษา C # ซึ่งทำงานโดยใช้ NUnit framework (ไม่ใช่กรณีหน่วยเช่นนี้)

การทดสอบ UI เหล่านี้ขึ้นอยู่กับลำดับการดำเนินการอย่างแน่นอนเนื่องจากการทดสอบอื่น ๆ จำเป็นต้องเพิ่มข้อมูลบางส่วนเป็นเงื่อนไขเบื้องต้น (เป็นไปไม่ได้ที่จะทำตามขั้นตอนในการทดสอบทุกครั้ง)

ตอนนี้หลังจากเพิ่มกรณีทดสอบที่ 10 แล้วฉันเห็นว่า NUnit ต้องการเรียกใช้ตามลำดับนี้: Test_1 Test_10 Test_2 Test_3 ..

ดังนั้นฉันเดาว่าฉันต้องเรียงชื่อเคสทดสอบตามตัวอักษรในตอนนี้ แต่จะเป็นการดีที่จะเพิ่มคุณสมบัติเล็ก ๆ ในการควบคุมคำสั่งการดำเนินการลงใน NUnit


9
ไม่เห็นด้วยกับ Arran: การทดสอบ UI เป็นลำดับขั้นตอนเล็ก ๆ โดยเนื้อแท้ แต่ละขั้นตอนจะเป็นการทดสอบ (เหตุผล - ถ้าล้มเหลวฉันต้องรู้ว่าขั้นตอนใด) ลำดับสามารถเป็นอิสระ แต่ภายในลำดับต้องมีความสำคัญและหยุดเมื่อเกิดความล้มเหลว
Zasz

3

โดยปกติการทดสอบหน่วยควรเป็นอิสระ แต่ถ้าคุณต้องคุณสามารถตั้งชื่อวิธีการของคุณตามลำดับตัวอักษรเช่น:

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

2
ยกเว้นตอนนี้ชื่อจะต้องเรียงตามตัวอักษรซึ่งเป็นวิธีแก้ปัญหาที่แย่มาก :(

@ user166390 - ไม่ใช่มันไม่ได้แย่มาก ใช้งานได้และขึ้นอยู่กับพฤติกรรมที่บันทึกไว้ของ NUnit
tymtam

➕1ที่ดีพอสำหรับฉันมากขึ้นหากคุณเริ่มต้นการทดสอบของคุณกับa_ b_ t1_, t2_แทนหรืออาศัยง่ายที่จะพลาดตัวอักษรต่อท้าย
คริส Marisic

3

มีเหตุผลที่ดีมากในการใช้กลไกการสั่งซื้อการทดสอบ การทดสอบส่วนใหญ่ของฉันใช้แนวทางปฏิบัติที่ดีเช่นการตั้งค่า / การฉีกขาด คนอื่น ๆ ต้องการการตั้งค่าข้อมูลจำนวนมากซึ่งสามารถใช้ทดสอบคุณสมบัติต่างๆได้ จนถึงตอนนี้ฉันได้ใช้การทดสอบขนาดใหญ่เพื่อจัดการกับการทดสอบการรวม (Selenium Webdriver) เหล่านี้ อย่างไรก็ตามฉันคิดว่าโพสต์ที่แนะนำข้างต้นใน https://github.com/nunit/docs/wiki/Order-Attributeมีประโยชน์มาก นี่คือตัวอย่างว่าทำไมการสั่งซื้อจึงมีคุณค่ามาก:

  • ใช้ Selenium Webdriver เพื่อทำการทดสอบเพื่อดาวน์โหลดรายงาน
  • สถานะของรายงาน (ไม่ว่าจะดาวน์โหลดได้หรือไม่ก็ตาม) จะถูกแคชเป็นเวลา10 นาที
  • นั่นหมายความว่าก่อนการทดสอบทุกครั้งฉันต้องรีเซ็ตสถานะรายงานจากนั้นรอถึง10 นาทีก่อนที่สถานะจะได้รับการยืนยันว่ามีการเปลี่ยนแปลงจากนั้นตรวจสอบการดาวน์โหลดรายงานอย่างถูกต้อง
  • ไม่สามารถสร้างรายงานในทางปฏิบัติ / ทันเวลาผ่านการล้อเลียนหรือกลไกอื่นใดภายในกรอบการทดสอบเนื่องจากความซับซ้อน

เวลารอ 10 นาทีนี้ทำให้ชุดทดสอบช้าลง เมื่อคุณทวีคูณความล่าช้าในการแคชที่คล้ายกันในการทดสอบจำนวนมากจะใช้เวลามาก การสั่งซื้อการทดสอบอาจช่วยให้การตั้งค่าข้อมูลสามารถทำได้โดยเป็น "การทดสอบ" ที่จุดเริ่มต้นของชุดทดสอบโดยการทดสอบที่อาศัยแคชเพื่อหยุดการทำงานจะถูกดำเนินการในตอนท้ายของการทดสอบ


2

คำถามนี้เก่ามากแล้วในตอนนี้ แต่สำหรับผู้ที่สามารถเข้าถึงสิ่งนี้ได้จากการค้นหาฉันได้รับคำตอบที่ยอดเยี่ยมจาก user3275462 และ PvtVandals / Rico และเพิ่มลงในที่เก็บ GitHubพร้อมกับการอัปเดตของฉันเอง ฉันยังสร้างบล็อกโพสต์ที่เกี่ยวข้องพร้อมข้อมูลเพิ่มเติมที่คุณสามารถดูข้อมูลเพิ่มเติมได้

หวังว่านี่จะเป็นประโยชน์สำหรับคุณทุกคน นอกจากนี้ฉันมักชอบใช้แอตทริบิวต์ Category เพื่อแยกความแตกต่างของการทดสอบการรวมหรือการทดสอบแบบ end-to-end จากการทดสอบหน่วยจริงของฉัน คนอื่น ๆ ชี้ให้เห็นว่าการทดสอบหน่วยไม่ควรมีการพึ่งพาคำสั่ง แต่ประเภทการทดสอบอื่น ๆ มักจะทำดังนั้นจึงเป็นวิธีที่ดีในการเรียกใช้ประเภทการทดสอบที่คุณต้องการเท่านั้นและยังสั่งซื้อการทดสอบแบบ end-to-end เหล่านั้น


คุณสามารถช่วยฉันเกี่ยวกับปัญหาที่ฉันมีนี่คือลิงค์: stackoverflow.com/questions/31281395/…
Morgan Soren

1

ฉันแปลกใจที่ชุมชน 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
}

1

หากคุณกำลังใช้[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 Attribute


0

คุณไม่ควรขึ้นอยู่กับลำดับที่กรอบการทดสอบเลือกการทดสอบเพื่อดำเนินการการทดสอบควรแยกและเป็นอิสระ ในนั้นพวกเขาไม่ควรขึ้นอยู่กับการทดสอบอื่น ๆ ที่กำหนดขั้นตอนสำหรับพวกเขาหรือทำความสะอาดหลังจากนั้น นอกจากนี้ควรให้ผลลัพธ์เดียวกันโดยไม่คำนึงถึงลำดับของการดำเนินการทดสอบ (สำหรับภาพรวมของมทส.)

ฉันทำ Googling นิดหน่อย ตามปกติบางคนใช้กลอุบายลับๆล่อๆ (แทนที่จะแก้ปัญหาการทดสอบ / การออกแบบที่ซ่อนอยู่

  • การตั้งชื่อการทดสอบตามลำดับตัวอักษรเพื่อให้การทดสอบปรากฏตามลำดับที่พวกเขา 'ต้องการ' จึงจะดำเนินการได้ อย่างไรก็ตาม NUnit อาจเลือกที่จะเปลี่ยนพฤติกรรมนี้ด้วยการเปิดตัวในภายหลังจากนั้นการทดสอบของคุณจะถูกยกเลิก ตรวจสอบไบนารี NUnit ปัจจุบันไปยัง Source Control ได้ดีขึ้น
  • VS (IMHO สนับสนุนพฤติกรรมที่ไม่ถูกต้องด้วย 'เครื่องมือที่คล่องตัว') มีสิ่งที่เรียกว่า "การทดสอบตามสั่ง" ในกรอบการทดสอบ MS ฉันไม่เสียเวลาอ่านเลย แต่ดูเหมือนว่าจะมีเป้าหมายไปที่ผู้ชมกลุ่มเดียวกัน

ดูเพิ่มเติม: ลักษณะของการทดสอบที่ดี


มีบางครั้งที่คุณต้องการให้มีการดำเนินการทดสอบที่เร็วขึ้นก่อนการทดสอบระยะยาวโดยเฉพาะในการทดสอบการรวมและการยอมรับ ตัวอย่างเช่นในแอปบล็อก: คุณทดสอบการเข้าสู่ระบบก่อนเพราะหากฟีเจอร์นั้นไม่ทำงานการโพสต์จะไม่ทำงานดังนั้นจึงไม่มีประเด็นใดที่จะดำเนินการทดสอบนั้น (คุณสามารถหยุดนักวิ่งได้ด้วยตนเอง) แต่ถ้าคุณพยายามดำเนินการทดสอบต่อไปก็จะต้องใช้เวลามากขึ้น
Marcel Valdez Orozco

@MarcelValdezOrozco - คุณสามารถบรรลุเป้าหมายนั้นได้โดยแบ่งการทดสอบของคุณผ่านทาง dll ทางกายภาพที่แตกต่างกันหรือโดยใช้แท็ก / หมวดหมู่ คุณสามารถสร้างบิลด์สคริปต์ของคุณเพื่อเรียกใช้ dlls / หมวดหมู่ตามลำดับ โดยทั่วไปแล้วการอนุญาตให้มีการจัดลำดับการทดสอบมักจะนำไปสู่การทดสอบควบคู่ที่พัฒนาขึ้นอยู่กับการทดสอบข้างเคียง (เมื่อเวลาผ่านไป) AFAIR ในรุ่นใหญ่ถัดไปของ NUnit จะรองรับลำดับการทดสอบที่แตกต่างกันเช่นการสุ่มเป็นต้น
Gishu

2
การแบ่งพาร์ติชันการทดสอบประเภทเดียวกันเพิ่มเติม (ตัวอย่างเช่นการทดสอบการยอมรับ) ไม่สมเหตุสมผลและการแยกออกเป็น DLL อื่นโดยไม่จำเป็นจะเพิ่มความซับซ้อนทุกที่ไม่ว่าจะเป็นซอร์สโค้ดบิลด์สคริปต์สคริปต์ทดสอบโครงสร้างโปรเจ็กต์ ฯลฯ เพียงเพื่อจัดลำดับใหม่อย่างง่าย การทดสอบ
Marcel Valdez Orozco

การเปล่งแสง (โดยทั่วไปแล้วการล้อเลียน libs ทั้งหมด) เป็นเหตุผลว่าทำไมคำสั่งจึงมีความสำคัญ คุณไม่สามารถยกเลิกการโหลดโดเมนแอปของคุณได้และแม่ชีรัน (หากเรียกใช้การทดสอบทั้งหมดในแอสเซมบลี) จะเก็บโดเมนนั้นไว้สำหรับการทดสอบทั้งหมดใน 'การแก้ไข' เป็นอย่างน้อย หากการทดสอบหนึ่งสร้างประเภทเพื่อทดสอบบางสิ่งบางอย่างและการทดสอบอื่นขัดแย้งกับประเภทที่สร้างขึ้นนั้นเนื่องจากคำสั่งนั่นไม่ใช่การทดสอบที่ผิดพลาด พวกมันถูกแยกอย่างมีเหตุผลเพียงแต่ว่า nUnit ไม่ได้ให้การแยกที่เหมาะสมระหว่าง 'การทดสอบ' แต่ละครั้ง
Kelly Elton

6
นี่เป็นคำตอบที่ค่อนข้างน่าเชื่อถือและมันทำให้ตลกเพราะใช้กับการทดสอบหน่วยเท่านั้นและไม่สนใจว่าจะเป็นประโยชน์
tymtam

0

ในกรณีที่ใช้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
        }
    };
}

ตอนนี้ให้ใช้วิธีทดสอบและดูว่าเกิดอะไรขึ้น:

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

ผลลัพธ์จะเปลี่ยนไปและเราได้ลำดับและชื่อการทดสอบเช่น:

ใส่คำอธิบายภาพที่นี่

บันทึก:

  1. นี่เป็นเพียงตัวอย่างเพื่อแสดงวิธีการรับชื่อและลำดับในการทดสอบคำสั่งจะถูกนำมาใช้เป็นตัวเลข / ตามตัวอักษรดังนั้นหากคุณมีการทดสอบมากกว่าสิบครั้งฉันขอแนะนำให้ทำการทดสอบ 01, ทดสอบ 02 .... ทดสอบ 10, ทดสอบ 11 เป็นต้นเพราะถ้า คุณทำแบบทดสอบ 1 และในบางจุดทดสอบ 10 กว่าคำสั่งจะเป็นแบบทดสอบ 1 ทดสอบ 10 ทดสอบ 2 .. ฯลฯ
  2. อินพุตและคาดว่าจะเป็นประเภทสตริงออบเจ็กต์หรือคลาสแบบกำหนดเองก็ได้
  3. นอกจากนี้สิ่งที่ดีที่นี่คือคุณเห็นชื่อการทดสอบซึ่งสำคัญกว่า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.