इकाई परीक्षण को क्रमबद्ध रूप से (समानांतर में करने के बजाय) करें


99

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

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

मैंने xUnit.NET का उपयोग किया है, यह उम्मीद करते हुए कि इसकी व्यापकता के कारण, मुझे इसे परीक्षणों को क्रमिक रूप से चलाने के लिए मजबूर करने का एक तरीका मिल सकता है। हालाँकि, मेरा कोई भाग्य नहीं था। मैं उम्मीद कर रहा हूं कि एसओ पर यहां किसी ने एक समान मुद्दे का सामना किया है और जानता है कि क्रमिक रूप से चलाने के लिए यूनिट परीक्षण कैसे प्राप्त करें।

नोट: ServiceHost एक WCF वर्ग है, जो Microsoft द्वारा लिखा गया है। मेरे पास यह व्यवहार बदलने की क्षमता नहीं है। प्रत्येक सेवा समापन बिंदु को केवल एक बार होस्ट करना भी उचित व्यवहार है ... हालांकि, यह विशेष रूप से इकाई परीक्षण के लिए अनुकूल नहीं है।


क्या ServiceHost का यह विशेष व्यवहार कुछ ऐसा नहीं होगा जिसे आप संबोधित करना चाहें?
रॉबर्ट हार्वे

ServiceHost Microsoft द्वारा लिखा गया है। मेरा इस पर कोई नियंत्रण नहीं है। और तकनीकी रूप से बोलना, यह वैध व्यवहार है ... आपके पास प्रति समापन बिंदु एक से अधिक ServiceHost कभी नहीं होना चाहिए।
jrista

1
मेरे पास इसी तरह का मुद्दा था कि मैं TestServerडॉकटर में कई को चलाने की कोशिश कर रहा हूं । इसलिए मुझे एकीकरण परीक्षणों को क्रमबद्ध करना पड़ा।
एच-राय

जवाबों:


116

प्रत्येक परीक्षण वर्ग एक अद्वितीय परीक्षण संग्रह है और इसके तहत परीक्षण क्रम में चलेंगे, इसलिए यदि आप अपने सभी परीक्षणों को एक ही संग्रह में रखते हैं तो यह क्रमिक रूप से चलेगा।

XUnit में आप इसे प्राप्त करने के लिए निम्नलिखित परिवर्तन कर सकते हैं:

निम्नलिखित समानांतर में चलेगा:

namespace IntegrationTests
{
    public class Class1
    {
        [Fact]
        public void Test1()
        {
            Console.WriteLine("Test1 called");
        }

        [Fact]
        public void Test2()
        {
            Console.WriteLine("Test2 called");
        }
    }

    public class Class2
    {
        [Fact]
        public void Test3()
        {
            Console.WriteLine("Test3 called");
        }

        [Fact]
        public void Test4()
        {
            Console.WriteLine("Test4 called");
        }
    }
}

इसे अनुक्रमिक बनाने के लिए आपको बस एक ही संग्रह के तहत दोनों परीक्षा कक्षाएं लगाने की आवश्यकता है:

namespace IntegrationTests
{
    [Collection("Sequential")]
    public class Class1
    {
        [Fact]
        public void Test1()
        {
            Console.WriteLine("Test1 called");
        }

        [Fact]
        public void Test2()
        {
            Console.WriteLine("Test2 called");
        }
    }

    [Collection("Sequential")]
    public class Class2
    {
        [Fact]
        public void Test3()
        {
            Console.WriteLine("Test3 called");
        }

        [Fact]
        public void Test4()
        {
            Console.WriteLine("Test4 called");
        }
    }
}

अधिक जानकारी के लिए आप इस लिंक को देख सकते हैं


24
मुझे लगता है कि जवाब की सराहना की। काम करने लगता है और मुझे ग्रैन्युलैरिटी पसंद है, क्योंकि मेरे पास एक विधानसभा में समानांतर और गैर-समानांतर परीक्षण हैं।
इगंड

1
यह ऐसा करने का सही तरीका है, Xunit प्रलेखन रेफरी।
हाकोन के। ओलाफसेन

2
यह स्वीकृत उत्तर होना चाहिए क्योंकि आम तौर पर कुछ परीक्षण समानांतर (मेरे मामले में सभी यूनिट परीक्षण) में चलाए जा सकते हैं, लेकिन कुछ समानांतर में चलने पर बेतरतीब ढंग से विफल हो जाते हैं (मेरे मामले में इन-मेमोरी वेब क्लाइंट / सर्वर का उपयोग करने वाले), इसलिए एक है यदि कोई ऐसा चाहता है तो टेस्ट रनिंग का अनुकूलन कर सकता है।
अलेक्सई

2
यह मेरे लिए एक .net कोर प्रोजेक्ट में काम नहीं करता था जहां मैं एक साइक्लाइट डेटाबेस के साथ एकीकरण परीक्षण करता हूं। परीक्षण अभी भी समानांतर में निष्पादित किए गए थे। स्वीकृत जवाब ने हालांकि काम किया।
user1796440

इस उत्तर के लिए बहुत बहुत धन्यवाद! यह करने की आवश्यकता है क्योंकि मेरे पास विभिन्न वर्गों में स्वीकार्यता परीक्षण हैं जो दोनों एक ही टेस्टबेस से विरासत में प्राप्त हुए हैं और संगणना ईएफ कोर के साथ अच्छा नहीं खेल रहा है।
Kyanite

104

जैसा कि ऊपर कहा गया है, सभी अच्छे यूनिट परीक्षणों को 100% अलग-थलग किया जाना चाहिए। साझा स्थिति का उपयोग करना (जैसे staticकि प्रत्येक परीक्षण द्वारा संशोधित संपत्ति के आधार पर ) को बुरा अभ्यास माना जाता है।

कहा कि, अनुक्रम में xUnit परीक्षण चलाने के बारे में आपके प्रश्न का उत्तर है! मुझे ठीक उसी समस्या का सामना करना पड़ा क्योंकि मेरा सिस्टम एक स्थिर सेवा लोकेटर (जो आदर्श से कम है) का उपयोग करता है।

डिफ़ॉल्ट रूप से xUnit 2.x समानांतर में सभी परीक्षण चलाता है। यह CollectionBehaviorआपके विधानसभा में परिभाषित किया जा सकता है प्रति विधानसभा में संशोधित करके अपने परीक्षण परियोजना में Info.cs।

प्रति विधानसभा जुदाई उपयोग के लिए:

using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]

या सभी उपयोग में कोई समानांतरकरण के लिए:

[assembly: CollectionBehavior(DisableTestParallelization = true)]

उत्तरार्द्ध शायद आप चाहते हैं। समानांतरकरण और विन्यास के बारे में अधिक जानकारी xUnit प्रलेखन पर पाई जा सकती है ।


5
मेरे लिए, प्रत्येक वर्ग के भीतर तरीकों के बीच साझा संसाधन थे। एक कक्षा से एक परीक्षण चल रहा है, फिर एक दूसरे से, दोनों से परीक्षण तोड़ेंगे। मैं का उपयोग करके हल करने में सक्षम था [assembly: CollectionBehavior(CollectionBehavior.CollectionPerClass, DisableTestParallelization = true)]। आपको धन्यवाद, @Squiggle, मैं अपने सभी परीक्षण चला सकता हूं और कॉफी ले सकता हूं! :)
अलीलसन पिफर

2
अभिनव सक्सेना का उत्तर .NET कोर के लिए अधिक बारीक है।
येंफर

67

.NET कोर प्रोजेक्ट्स के लिए, इसके xunit.runner.jsonसाथ बनाएं :

{
  "parallelizeAssembly": false,
  "parallelizeTestCollections": false
}

इसके अलावा, आपका csprojहोना चाहिए

<ItemGroup>
  <None Update="xunit.runner.json"> 
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

पुराने .नेट कोर प्रोजेक्ट्स के लिए, आपके पास project.jsonहोना चाहिए

"buildOptions": {
  "copyToOutput": {
    "include": [ "xunit.runner.json" ]
  }
}

2
मुझे लगता है कि नवीनतम csproj डॉटनेट कोर बराबर <ItemGroup><None Include="xunit.runner.json" CopyToOutputDirectory="Always" /></ItemGroup>या समान होगा?
स्क्वीगल

3
यह मेरे लिए csproj में काम किया:<ItemGroup> <None Update="xunit.runner.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
skynyrd

क्या समीकरण को अक्षम करना XUnit सिद्धांतों के साथ काम करता है?
जॉन ज़ब्रोस्की

यह एकमात्र ऐसी चीज है जिसने मेरे लिए काम किया, मैंने जैसे दौड़ने की कोशिश की dotnet test --no-build -c Release -- xunit.parallelizeTestCollections=falseलेकिन यह मेरे लिए काम नहीं आया।
हार्वे

18

.NET कोर परियोजनाओं के लिए, आप https://xunit.github.io/docs/configuring-with-json.htmlxunit.runner.json पर दस्तावेज के रूप में एक फाइल के साथ xUnit को कॉन्फ़िगर कर सकते हैं ।

समानांतर परीक्षण निष्पादन को रोकने के लिए आपको जो सेटिंग बदलने की आवश्यकता है parallelizeTestCollections, वह trueनिम्न है :

यह निर्धारित करें कि trueक्या विधानसभा इस विधानसभा के अंदर एक दूसरे के खिलाफ समानांतर में परीक्षण चलाने के लिए तैयार है। ... falseइस परीक्षण असेंबली के भीतर सभी समानांतरकरण को अक्षम करने के लिए इसे सेट करें ।

JSON स्कीमा प्रकार: बूलियन
डिफ़ॉल्ट मान:true

तो xunit.runner.jsonइस उद्देश्य के लिए एक न्यूनतम जैसा दिखता है

{
    "parallelizeTestCollections": false
}

डॉक्स में उल्लेख किया गया है, इस फ़ाइल को अपनी बिल्ड में शामिल करना याद रखें, या तो:

  • यदि Visual Studio, या फ़ाइल में फ़ाइल के गुणों में नया है तो कॉपी करने के लिए आउटपुट निर्देशिका में प्रतिलिपि सेट करना
  • जोड़ा जा रहा है

    <Content Include=".\xunit.runner.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>

    आपकी .csprojफ़ाइल पर, या

  • जोड़ा जा रहा है

    "buildOptions": {
      "copyToOutput": {
        "include": [ "xunit.runner.json" ]
      }
    }

    आपकी project.jsonफ़ाइल पर

आपके प्रोजेक्ट के प्रकार पर निर्भर करता है।

अंत में, उपरोक्त के अलावा , यदि आप विजुअल स्टूडियो का उपयोग कर रहे हैं, तो सुनिश्चित करें कि आपने गलती से रन टेस्ट इन समानांतर बटन पर क्लिक नहीं किया है , जिसके कारण आप समानांतर में बंद होने पर भी परीक्षण समानांतर चलेंगे xunit.runner.json। Microsoft के UI डिज़ाइनरों ने इस बटन को अनपेक्षित रूप से, नोटिस करने में कठिन, और टेस्ट एक्सप्लोरर में "रन ऑल" बटन से लगभग एक सेंटीमीटर की दूरी पर बनाया है , बस इस मौके को अधिकतम करने के लिए कि आप इसे गलती से मारेंगे और पता नहीं क्यों आपके परीक्षण होंगे अचानक असफल हो रहे हैं:

बटन के साथ स्क्रीनशॉट चक्कर लगाया


@ जॉनहोब्रोस्की मुझे आपके सुझाए गए संपादन समझ में नहीं आते हैं । ReSharper का किसी चीज से क्या लेना-देना है? मुझे लगता है कि शायद मैंने इसे स्थापित किया था जब मैंने ऊपर उत्तर लिखा था, लेकिन क्या यहां सब कुछ स्वतंत्र नहीं है कि आप इसका उपयोग कर रहे हैं या नहीं? संपादित करने के लिए आप जिस पृष्ठ को लिंक करते हैं, उसका किसी xunit.runner.jsonफ़ाइल को निर्दिष्ट करने के साथ क्या करना है ? और xunit.runner.jsonधारावाहिकों को क्रमिक रूप से चलाने के साथ क्या करना है?
मार्क अमेरी

मैं क्रमिक रूप से चलाने के लिए अपने परीक्षण प्राप्त करने की कोशिश कर रहा हूं, और शुरू में लगा कि यह मुद्दा ReSharper से संबंधित है (क्योंकि ReSharper के पास Visual Studio टेस्ट एक्सप्लोरर की तरह "रन टेस्ट इन पैरलल" बटन नहीं है)। हालांकि, ऐसा लगता है जब मैं [थ्योरी] का उपयोग करता हूं, मेरे परीक्षण अलग-थलग नहीं हैं। यह अजीब है, क्योंकि मैं जो कुछ भी पढ़ता हूं वह बताता है कि एक कक्षा सबसे छोटी समानांतर इकाई है।
जॉन ज़ब्रोस्की

9

यह पुराना सवाल है लेकिन मैं अपने जैसे नए खोज करने वाले लोगों के लिए एक समाधान लिखना चाहता था :)

ध्यान दें: मैं इस विधि का उपयोग xunit संस्करण 2.4.1 के साथ डॉट नेट कोर WebUI एकीकरण परीक्षणों में करता हूं।

NonParallelCollectionDefinitionClass नाम का एक खाली वर्ग बनाएं और फिर नीचे इस वर्ग को CollectionDefinition विशेषता दें। (महत्वपूर्ण हिस्सा DisableParallelization = true सेटिंग है।)

using Xunit;

namespace WebUI.IntegrationTests.Common
{
    [CollectionDefinition("Non-Parallel Collection", DisableParallelization = true)]
    public class NonParallelCollectionDefinitionClass
    {
    }
}

उसके बाद उस श्रेणी में संग्रह विशेषता जोड़ें, जिसे आप नहीं चाहते कि वह नीचे के समानान्तर चले। (महत्वपूर्ण हिस्सा संग्रह का नाम है। यह संग्रह में उपयोग किए गए नाम के साथ समान होना चाहिए)

namespace WebUI.IntegrationTests.Controllers.Users
{
    [Collection("Non-Parallel Collection")]
    public class ChangePassword : IClassFixture<CustomWebApplicationFactory<Startup>>
    ...

जब हम ऐसा करते हैं, तो सबसे पहले अन्य समानांतर परीक्षण चलते हैं। उसके बाद अन्य परीक्षण जिसमें संग्रह ("गैर-समानांतर संग्रह") विशेषता चलती है।


6

आप प्लेलिस्ट का उपयोग कर सकते हैं

परीक्षण विधि पर राइट क्लिक करें -> प्लेलिस्ट में जोड़ें -> नई प्लेलिस्ट

फिर आप निष्पादन आदेश को निर्दिष्ट कर सकते हैं, डिफ़ॉल्ट है, जैसा कि आप उन्हें प्ले सूची में जोड़ते हैं, लेकिन आप चाहें तो प्लेलिस्ट फ़ाइल को बदल सकते हैं

यहां छवि विवरण दर्ज करें


5

मुझे विवरण नहीं पता है, लेकिन ऐसा लगता है कि आप इकाई परीक्षण के बजाय एकीकरण परीक्षण करने की कोशिश कर रहे होंगे । यदि आप पर निर्भरता को अलग कर सकते हैं , तो इससे आपकी परीक्षा आसान (और तेज) हो जाएगी। इसलिए (उदाहरण के लिए) आप स्वतंत्र रूप से निम्नलिखित परीक्षण कर सकते हैं:ServiceHost

  • कॉन्फ़िगरेशन रीडिंग क्लास
  • ServiceHost factory (संभवतः एकीकरण परीक्षण के रूप में)
  • इंजन वर्ग जो ए IServiceHostFactoryऔर ए लेता हैIConfiguration

ऐसे उपकरण जो आइसोलेशन (मॉकिंग) फ्रेमवर्क और (वैकल्पिक रूप से) आईओसी कंटेनर फ्रेमवर्क को शामिल करने में मदद करेंगे। देख:


मैं एकीकरण परीक्षण करने की कोशिश नहीं कर रहा हूँ। मुझे वास्तव में इकाई परीक्षण करने की आवश्यकता है। मैं पूरी तरह से TDD / BDD की शर्तों और प्रथाओं (IoC, DI, Mocking, इत्यादि) से वाकिफ हूं, इसलिए मिल की तरह का रन बनाना कारखानों को बनाने और इंटरफेस का उपयोग करने के लिए नहीं है, जिसकी मुझे आवश्यकता है (इसके पहले से ही, ServiceHost के मामले को छोड़कर।) ServiceHost एक निर्भरता नहीं है जिसे अलग किया जा सकता है, क्योंकि यह ठीक से नकली नहीं है (.NET सिस्टम नेमस्पेस के बहुत से।) मुझे वास्तव में इकाई परीक्षणों को क्रमिक रूप से चलाने के लिए एक तरीका चाहिए।
जिस्टा

1
@ जिरस्टा - आपके कौशल पर कोई मामूली इरादा नहीं था। मैं WCF डेवलपर नहीं हूं, लेकिन क्या इंजन के लिए रैपर पर इंटरफेस के साथ ServiceHost के आसपास रैपर को वापस करना संभव होगा? या शायद ServiceHosts के लिए एक कस्टम कारखाना?
ट्रूविल

होस्टिंग इंजन किसी भी ServiceHosts को वापस नहीं करता है। यह वास्तव में कुछ भी वापस नहीं करता है, यह केवल आंतरिक रूप से ServiceHosts के निर्माण, उद्घाटन और समापन का प्रबंधन करता है। मैं सभी मौलिक WCF प्रकारों को लपेट सकता हूं, लेकिन यह बहुत काम है जिसे मैं वास्तव में करने के लिए अधिकृत नहीं हूं। इसके अलावा, जैसा कि यह निकला, समस्या समानांतर निष्पादन के कारण नहीं है, और अभी भी सामान्य ऑपरेशन के दौरान होगी। मैंने समस्या के बारे में SO पर यहाँ एक और प्रश्न शुरू किया, और उम्मीद है कि मुझे उत्तर मिल जाएगा।
जिस्टा

@TrueWill: BTW, मैं आपके बारे में अपने कौशल को थोड़ा कम करने के बारे में चिंतित नहीं था ... मैं बस बहुत सारे रन-ऑफ-द-मिल उत्तर नहीं चाहता था जो इकाई परीक्षण के बारे में सभी सामान्य सामान को कवर करते हैं। मुझे एक बहुत ही विशिष्ट समस्या पर एक त्वरित उत्तर की आवश्यकता थी। क्षमा करें अगर मैं थोड़ा भीषण आया, तो मेरा इरादा नहीं था। इस काम को करने के लिए मेरे पास बहुत सीमित समय है।
जिस्टा

3

शायद आप उन्नत इकाई परीक्षण का उपयोग कर सकते हैं । यह आपको उस अनुक्रम को परिभाषित करने की अनुमति देता है जिसमें आप परीक्षण चलाते हैं । तो आपको उन परीक्षणों को होस्ट करने के लिए एक नई सीएस फाइल बनानी पड़ सकती है।

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

[Test]
[Sequence(16)]
[Requires("POConstructor")]
[Requires("WorkOrderConstructor")]
public void ClosePO()
{
  po.Close();

  // one charge slip should be added to both work orders

  Assertion.Assert(wo1.ChargeSlipCount==1,
    "First work order: ChargeSlipCount not 1.");
  Assertion.Assert(wo2.ChargeSlipCount==1,
    "Second work order: ChargeSlipCount not 1.");
  ...
}

क्या मुझे पता है कि यह काम करता है।


बढ़िया लेख। मैंने वास्तव में इसे सीपी पर बुकमार्क किया था। लिंक के लिए धन्यवाद, लेकिन जैसा कि यह निकला, समस्या बहुत गहरी लगती है, क्योंकि परीक्षण धावक समानांतर में परीक्षण चलाने के लिए नहीं लगते हैं।
जिस्टा

2
रुको, पहले आप कहते हैं कि आप परीक्षण समानांतर में नहीं चलाना चाहते हैं, और फिर आप कहते हैं कि समस्या यह है कि परीक्षण धावक समानांतर में परीक्षण नहीं चलाते हैं ... तो कौन सा है?
ग्रिटिटोन

आपके द्वारा प्रदान किया गया लिंक अब काम नहीं करता है। और यह कुछ आप xunit के साथ कर सकते हैं?
एलन वांग

1

मेरे लिए, .Net कोर कंसोल एप्लिकेशन में, जब मैं परीक्षण विधियों (न कि कक्षाओं) को समकालिक रूप से चलाना चाहता था, जो एकमात्र समाधान था, वह इस ब्लॉग में वर्णित था: xUnit: टेस्ट एक्ज़ीक्यूशन ऑर्डर को नियंत्रित करें


0

मैंने विशेषता को आधार वर्ग में [संग्रह ("अनुक्रमिक") जोड़ा है :

    namespace IntegrationTests
    {
      [Collection("Sequential")]
      public class SequentialTest : IDisposable
      ...


      public class TestClass1 : SequentialTest
      {
      ...
      }

      public class TestClass2 : SequentialTest
      {
      ...
      }
    }

0

अब तक सुझाए गए किसी भी जवाब ने मेरे लिए काम नहीं किया। मेरे पास XUnit 2.4.1 के साथ एक डॉटनेट कोर ऐप है। मैंने इसके बजाय प्रत्येक यूनिट टेस्ट में लॉक लगाकर वर्कअराउंड के साथ वांछित व्यवहार हासिल किया। मेरे मामले में, मुझे रनिंग ऑर्डर की कोई परवाह नहीं थी, बस परीक्षण अनुक्रमिक थे।

public class TestClass
{
    [Fact]
    void Test1()
    {
        lock (this)
        {
            //Test Code
        }
    }

    [Fact]
    void Test2()
    {
        lock (this)
        {
            //Test Code
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.