xUnit.net: वैश्विक सेटअप + आंसू?


98

यह प्रश्न इकाई परीक्षण ढांचे xUnit.net के बारे में है ।

किसी भी परीक्षण को निष्पादित करने से पहले मुझे कुछ कोड चलाने की आवश्यकता है, और सभी परीक्षणों के बाद भी कुछ कोड। मैंने सोचा कि वैश्विक आरंभीकरण और समाप्ति कोड को इंगित करने के लिए किसी प्रकार की विशेषता या मार्कर इंटरफ़ेस होना चाहिए, लेकिन उन्हें ढूंढ नहीं सका।

वैकल्पिक रूप से, यदि मैं xUnit को प्रोग्रामेटिक रूप से आमंत्रित करता हूं, तो मैं यह भी प्राप्त कर सकता हूं कि मुझे निम्नलिखित कोड के साथ क्या चाहिए:

static void Main()
{
    try
    {
        MyGlobalSetup();
        RunAllTests();  // What goes into this method?
    }
    finally
    {
        MyGlobalTeardown();
    }
}

क्या कोई मुझे इस बारे में कोई संकेत दे सकता है कि घोषित रूप से या प्रोग्रामेटिक रूप से कुछ वैश्विक सेटअप / फाड़ कोड कैसे चलाएं?


1
मुझे लगता है कि यहाँ जवाब है: stackoverflow.com/questions/12379949/…
the_joric

जवाबों:


118

जहाँ तक मुझे पता है, xUnit में वैश्विक आरंभीकरण / आंसू विस्तार बिंदु नहीं है। हालाँकि, इसे बनाना आसान है। बस एक बेस टेस्ट क्लास बनाएं IDisposable, जो कंस्ट्रक्टर में आपकी इनिशियलाइज़ेशन करे और IDisposable.Disposeमेथड में आपका फाड़ हो । यह इस तरह दिखेगा:

public abstract class TestsBase : IDisposable
{
    protected TestsBase()
    {
        // Do "global" initialization here; Called before every test method.
    }

    public void Dispose()
    {
        // Do "global" teardown here; Called after every test method.
    }
}

public class DummyTests : TestsBase
{
    // Add test methods
}

हालांकि, प्रत्येक कॉल के लिए बेस क्लास सेटअप और टियरडाउन कोड निष्पादित किया जाएगा। यह वह नहीं हो सकता जो आप चाहते हैं, क्योंकि यह बहुत कुशल नहीं है। एक अधिक अनुकूलित संस्करण यह IClassFixture<T>सुनिश्चित करने के लिए इंटरफ़ेस का उपयोग करेगा कि वैश्विक आरंभीकरण / फाड़ कार्यक्षमता केवल एक बार कहा जाता है। इस संस्करण के लिए, आप अपने परीक्षण वर्ग से एक आधार वर्ग का विस्तार नहीं करते हैं, लेकिन उस IClassFixture<T>इंटरफ़ेस को कार्यान्वित करते हैं जहां Tआपके स्थिरता वर्ग को संदर्भित किया जाता है:

using Xunit;

public class TestsFixture : IDisposable
{
    public TestsFixture ()
    {
        // Do "global" initialization here; Only called once.
    }

    public void Dispose()
    {
        // Do "global" teardown here; Only called once.
    }
}

public class DummyTests : IClassFixture<TestsFixture>
{
    public DummyTests(TestsFixture data)
    {
    }
}

यह परीक्षण के तहत हर वर्ग के लिए केवल एक बार चलाने के निर्माण में परिणाम देगाTestsFixture । यह इस प्रकार निर्भर करता है कि आप दोनों विधियों में से किसे चुनना चाहते हैं।


4
ऐसा लगता है कि IUseFixture अब मौजूद नहीं है, इसकी जगह IClassFixture ने ले ली है।
GaTechThomas

9
जबकि यह काम करता है, मुझे लगता है कि Geir Sagberg के उत्तर में CollectionFixture इस परिदृश्य के लिए बेहतर है क्योंकि इसे विशेष रूप से इस उद्देश्य के लिए डिज़ाइन किया गया था। आपको अपनी परीक्षण कक्षाओं को भी विरासत में प्राप्त करने की आवश्यकता नहीं है, आप बस उन्हें [Collection("<name>")]विशेषता के साथ चिह्नित करते हैं
मिशेल

8
क्या एसिंक्स सेटअप और टियरडाउन करने का कोई तरीका है?
एंड्री

ऐसा लगता है जैसे MS ने IClassFixture समाधान को भी लागू किया है। docs.microsoft.com/en-us/aspnet/core/test/...
lbrahim

3
XUnit तीन आरंभीकरण विकल्प प्रदान करता है: प्रति परीक्षण विधि, प्रति परीक्षण कक्षा और कई परीक्षण कक्षाओं के लिए। दस्तावेज़ यहाँ है: xunit.net/docs/sared-context
GHN

48

मैं उसी उत्तर की तलाश में था, और इस समय xUnit प्रलेखन क्लास फिक्स्चर और संग्रह फिक्स्चर को कैसे लागू किया जाए, इसके बारे में बहुत उपयोगी है जो डेवलपर्स को क्लास या क्लास स्तर के समूह में सेटअप / फाड़ कार्यक्षमता की एक विस्तृत श्रृंखला देता है। यह गीर सैगबर्ग के जवाब के अनुरूप है, और यह देखने के लिए अच्छा कंकाल कार्यान्वयन देता है कि इसे कैसा दिखना चाहिए।

https://xunit.github.io/docs/shared-context.html

संग्रह फिक्स्चर कब उपयोग करें: जब आप एक एकल परीक्षण संदर्भ बनाना चाहते हैं और इसे कई परीक्षण कक्षाओं में परीक्षणों के बीच साझा करते हैं, और परीक्षण कक्षाओं में सभी परीक्षण समाप्त होने के बाद इसे साफ किया है।

कभी-कभी आप कई परीक्षण कक्षाओं के बीच एक फ़िक्चर ऑब्जेक्ट साझा करना चाहेंगे। वर्ग जुड़नार के लिए उपयोग किया जाने वाला डेटाबेस उदाहरण एक महान उदाहरण है: आप एक डेटाबेस को परीक्षण डेटा के एक सेट के साथ प्रारंभ करना चाहते हैं, और फिर उस परीक्षण डेटा को कई परीक्षण कक्षाओं द्वारा उपयोग के लिए छोड़ सकते हैं। आप कई परीक्षण वर्ग में परीक्षणों के बीच एक ही वस्तु उदाहरण साझा करने के लिए xUnit.net की संग्रह स्थिरता सुविधा का उपयोग कर सकते हैं।

संग्रह जुड़नार का उपयोग करने के लिए, आपको निम्नलिखित कदम उठाने की आवश्यकता है:

फ़िक्चर क्लास बनाएँ, और फ़िक्चर क्लास कंस्ट्रक्टर में स्टार्टअप कोड डालें। यदि फ़िक्चर क्लास को क्लीनअप करने की आवश्यकता है, तो फ़िक्सेरिटी क्लास पर आईडीसॉपी को लागू करें और क्लीनअप कोड को डिस्पोज़ () विधि में डालें। संग्रह परिभाषा वर्ग बनाएं, इसे [CollectionDefinition] विशेषता के साथ सजाते हुए, यह एक अनूठा नाम देता है जो परीक्षण संग्रह की पहचान करेगा। संग्रह परिभाषा वर्ग में ICollectionFixture <> जोड़ें। [संग्रह] विशेषता को सभी परीक्षण वर्गों में जोड़ें, जो संग्रह का हिस्सा होगा, जो आपके द्वारा संग्रह संग्रह परिभाषा वर्ग [[CollectionDefinition] विशेषता के लिए प्रदान किए गए अद्वितीय नाम का उपयोग कर रहा है। यदि परीक्षण वर्गों को स्थिरता उदाहरण तक पहुंच की आवश्यकता है, तो इसे एक निर्माता तर्क के रूप में जोड़ें, और यह स्वचालित रूप से प्रदान किया जाएगा। ये रहा एक सरल उदाहरण:

public class DatabaseFixture : IDisposable
{
    public DatabaseFixture()
    {
        Db = new SqlConnection("MyConnectionString");

        // ... initialize data in the test database ...
    }

    public void Dispose()
    {
        // ... clean up test data from the database ...
    }

    public SqlConnection Db { get; private set; }
}

[CollectionDefinition("Database collection")]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{
    // This class has no code, and is never created. Its purpose is simply
    // to be the place to apply [CollectionDefinition] and all the
    // ICollectionFixture<> interfaces.
}

[Collection("Database collection")]
public class DatabaseTestClass1
{
    DatabaseFixture fixture;

    public DatabaseTestClass1(DatabaseFixture fixture)
    {
        this.fixture = fixture;
    }
}

[Collection("Database collection")]
public class DatabaseTestClass2
{
    // ...
}

xUnit.net संग्रह जुड़नार को कक्षा जुड़नार की तरह ही व्यवहार करता है, सिवाय इसके कि एक संग्रह स्थिरता का जीवनकाल लंबा होता है: यह संग्रह में किसी भी परीक्षण वर्ग में किसी भी परीक्षण को चलाने से पहले बनाया जाता है, और इसे साफ नहीं किया जाएगा संग्रह में सभी परीक्षण कक्षाएं चलने तक समाप्त हो गई हैं।

टेस्ट कलेक्शन को IClassFixचर <> से भी सजाया जा सकता है। xUnit.net इसे मानता है, हालांकि परीक्षण संग्रह में प्रत्येक व्यक्तिगत परीक्षण वर्ग को वर्ग निर्धारण के साथ सजाया गया था।

टेस्ट कलेक्शन भी उसी तरह प्रभावित करते हैं जिस तरह से xUnit.net उन्हें समानांतर में चलाते हुए परीक्षण चलाता है। अधिक जानकारी के लिए, समानांतर में रनिंग टेस्ट देखें।

महत्वपूर्ण नोट: फिक्स्चर को उसी विधानसभा में होना चाहिए जो परीक्षण उनका उपयोग करता है।


1
"टेस्ट कलेक्शन को IClassFixचर <> के साथ भी सजाया जा सकता है। xUnit.net इस तरह व्यवहार करता है, जैसे टेस्ट कलेक्शन में प्रत्येक व्यक्तिगत टेस्ट क्लास को क्लास फिक्सेशन से सजाया गया हो।" कोई भी मौका मुझे उसका एक उदाहरण मिल सकता है? मैं इसे काफी नहीं समझता।
rtf

@TannerFaulkner वर्ग निर्धारण एक तरीका है जिसमें आप एक पारंपरिक .net Unit Test Project के साथ क्लास लेवल सेटअप और फाडाउन कर सकते हैं, जब आपके पास टेस्ट इनिशियलाइज़ मेथड होता है: [TestInitialize] पब्लिक वशीकरण प्रारंभ () {
लैरी स्मिथ

मेरे पास एकमात्र मुद्दा यह है कि आपको Collection"वैश्विक" सेटअप होने के लिए विशेषता के साथ अपने परीक्षण वर्गों को सजाने की आवश्यकता है। इसका मतलब है, अगर आपके पास कुछ भी है जो आप सेटअप से पहले चाहते हैं-परीक्षण चला है, तो आपको इस विशेषता के साथ -all- परीक्षण कक्षाओं को सजाने की आवश्यकता है। यह मेरी राय में बहुत भंगुर है, क्योंकि एक एकल परीक्षण वर्ग को सजाने के लिए त्रुटियों को ट्रैक करना मुश्किल हो सकता है। यह अच्छा होगा यदि xUnit ने वास्तव में वैश्विक सेटअप और फाड़ का रास्ता बनाया।
राशि

13

एक आसान आसान उपाय है। Fody.ModuleInit प्लगइन का उपयोग करें

https://github.com/Fody/ModuleInit

यह एक नूगट पैकेज है और जब आप इसे स्थापित करते हैं तो यह ModuleInitializer.csप्रोजेक्ट में एक नई फ़ाइल को जोड़ता है । यहाँ एक स्थैतिक विधि है जो निर्माण के बाद विधानसभा में बुनी जाती है और जैसे ही विधानसभा भरी जाती है और कुछ भी चलने से पहले उसे चलाया जाता है।

मैं इसका उपयोग सॉफ्टवेयर लाइसेंस को एक पुस्तकालय में अनलॉक करने के लिए करता हूं जिसे मैंने खरीदा है। मैं हमेशा प्रत्येक परीक्षण में लाइसेंस को अनलॉक करना भूल गया था और यहां तक ​​कि एक बेस क्लास से परीक्षण को प्राप्त करना भूल गया था जो इसे अनलॉक करेगा। इस लाइब्रेरी को लिखने वाली उज्ज्वल स्पार्क्स, आपको यह बताने के बजाय कि यह लाइसेंस बंद थी, सूक्ष्म संख्यात्मक त्रुटियों को प्रस्तुत करती है, जिसके कारण परीक्षण विफल हो जाते हैं या पास नहीं होना चाहिए। आप कभी नहीं जान पाएंगे कि आपने पुस्तकालय को सही ढंग से अनलॉक किया है या नहीं। तो अब मेरा मॉड्यूल init जैसा दिखता है

/// <summary>
/// Used by the ModuleInit. All code inside the Initialize method is ran as soon as the assembly is loaded.
/// </summary>
public static class ModuleInitializer
{
    /// <summary>
    /// Initializes the module.
    /// </summary>
    public static void Initialize()
    {
            SomeLibrary.LicenceUtility.Unlock("XXXX-XXXX-XXXX-XXXX-XXXX");
    }
}

और इस विधानसभा में रखे गए सभी परीक्षणों में उनके लिए लाइसेंस को सही ढंग से अनलॉक किया जाएगा।


2
ठोस विचार; दुर्भाग्य से यह DNX इकाई परीक्षणों के साथ अभी तक काम नहीं करता है।
जेफ डनलप

12

SetUp / TearDown-code को कई वर्गों के बीच साझा करने के लिए, आप xUnit के CollectionFixture का उपयोग कर सकते हैं ।

उद्धरण:

संग्रह जुड़नार का उपयोग करने के लिए, आपको निम्नलिखित कदम उठाने की आवश्यकता है:

  • फ़िक्चर क्लास बनाएँ, और स्टार्टअप कोड को फ़िक्चर क्लास कंस्ट्रक्टर में डालें।
  • यदि फ़िक्चर क्लास को क्लीनअप करने की ज़रूरत है, तो फ़िक्सेचर क्लास पर आईडीसॉपी को लागू करें, और क्लीनअप कोड को डिस्पोज़ () विधि में डालें।
  • संग्रह परिभाषा वर्ग बनाएं, इसे [CollectionDefinition] विशेषता के साथ सजाते हुए, यह एक अनूठा नाम देता है जो परीक्षण संग्रह की पहचान करेगा।
  • संग्रह परिभाषा वर्ग में ICollectionFixture <> जोड़ें।
  • [संग्रह] विशेषता को सभी परीक्षण वर्गों में जोड़ें, जो संग्रह का हिस्सा होगा, जो आपके द्वारा संग्रह संग्रह परिभाषा वर्ग [[CollectionDefinition] विशेषता के लिए प्रदान किए गए अद्वितीय नाम का उपयोग कर रहा है।
  • यदि परीक्षण वर्गों को स्थिरता उदाहरण तक पहुंच की आवश्यकता है, तो इसे एक निर्माता तर्क के रूप में जोड़ें, और यह स्वचालित रूप से प्रदान किया जाएगा।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.