5

मैं छोटे परीक्षणों में एक बड़े परीक्षण को विभाजित करने में सक्षम होना चाहता हूं ताकि जब छोटे परीक्षण पास हों तो उनका मतलब है कि बड़ा परीक्षण भी पास होगा (इसलिए चलाने का कोई कारण नहीं है मूल बड़ा परीक्षण)। मैं ऐसा इसलिए करना चाहता हूं क्योंकि छोटे परीक्षण आमतौर पर कम समय लेते हैं, कम प्रयास करते हैं और कम नाजुक होते हैं। मैं जानना चाहता हूं कि टेस्ट डिज़ाइन पैटर्न या सत्यापन उपकरण हैं जो इस परीक्षण को एक मजबूत तरीके से विभाजित करने में मेरी सहायता कर सकते हैं।छोटे परीक्षणों के सेट पर एक परीक्षण को विभाजित करना

मुझे डर है कि छोटे परीक्षणों और मूल परीक्षण के बीच कनेक्शन खो जाता है जब कोई छोटे परीक्षणों के सेट में कुछ बदलता है। एक और डर यह है कि छोटे परीक्षणों का सेट वास्तव में बड़े परीक्षण को कवर नहीं करता है।

मैं क्या कर रहा हूँ पर निशाना का एक उदाहरण:

//Class under test 
class A { 

    public void setB(B b){ this.b = b; } 

    public Output process(Input i){ 
    return b.process(doMyProcessing(i)); 
    } 

    private InputFromA doMyProcessing(Input i){ .. } 

    .. 

} 

//Another class under test 
class B { 

    public Output process(InputFromA i){ .. } 

    .. 

} 

//The Big Test 
@Test 
public void theBigTest(){ 
A systemUnderTest = createSystemUnderTest(); // <-- expect that this is expensive 

Input i = createInput(); 

Output o = systemUnderTest.process(i); // <-- .. or expect that this is expensive 

assertEquals(o, expectedOutput()); 
} 

//The splitted tests 

@PartlyDefines("theBigTest") // <-- so something like this should come from the tool.. 
@Test 
public void smallerTest1(){ 
    // this method is a bit too long but its just an example.. 
    Input i = createInput(); 
    InputFromA x = expectedInputFromA(); // this should be the same in both tests and it should be ensured somehow 
    Output expected = expectedOutput(); // this should be the same in both tests and it should be ensured somehow 

    B b = mock(B.class); 
    when(b.process(x)).thenReturn(expected); 

    A classUnderTest = createInstanceOfClassA(); 
    classUnderTest.setB(b); 

    Output o = classUnderTest.process(i); 

    assertEquals(o, expected); 
    verify(b).process(x); 
    verifyNoMoreInteractions(b); 
} 

@PartlyDefines("theBigTest") // <-- so something like this should come from the tool.. 
@Test 
public void smallerTest2(){ 
    InputFromA x = expectedInputFromA(); // this should be the same in both tests and it should be ensured somehow 
    Output expected = expectedOutput(); // this should be the same in both tests and it should be ensured somehow 

    B classUnderTest = createInstanceOfClassB(); 

    Output o = classUnderTest.process(x); 

    assertEquals(o, expected); 
} 

उत्तर

2

पहला सुझाव जो मैं करूँगा वह लाल (असफल) पर आपके परीक्षणों को फिर से कारक बनाना है। ऐसा करने के लिए, आपको अस्थायी रूप से अपना उत्पादन कोड तोड़ना होगा। इस तरह, आप जानते हैं कि परीक्षण अभी भी मान्य हैं।

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

बड़े परीक्षण के लिए अलग-अलग छोटे परीक्षणों को पकड़ने के लिए एक अलग वर्ग का उपयोग करने का सबसे बड़ा लाभ यह है कि आप सेटअप और आंसू विधियों का लाभ उठा सकते हैं।

// this should be the same in both tests and it should be ensured somehow

सेटअप विधि के लिए

(JUnit, एक विधि @Before साथ एनोटेट में): आपके मामले में, मैं लाइनों आप के साथ टिप्पणी की है कदम होगा। यदि आपके पास कुछ असामान्य रूप से महंगा सेटअप है जो करने की आवश्यकता है, तो अधिकांश xUnit परीक्षण ढांचे के पास एक सेटअप विधि को परिभाषित करने का एक तरीका होता है जो सभी परीक्षणों से पहले एक बार चलता है। जुनीट में, यह public static void विधि है जिसमें @BeforeClass एनोटेशन है।

यदि परीक्षण डेटा अपरिवर्तनीय है, तो मैं चर को स्थिरांक के रूप में परिभाषित करता हूं।

public class TheBigTest { 

    // If InputFromA is immutable, it could be declared as a constant 
    private InputFromA x; 
    // If Output is immutable, it could be declared as a constant 
    private Output expected; 

    // You could use 
    // @BeforeClass public static void setupExpectations() 
    // instead if it is very expensive to setup the data 
    @Before 
    public void setUpExpectations() throws Exception { 
     x = expectedInputFromA(); 
     expected = expectedOutput(); 
    } 

    @Test 
    public void smallerTest1(){ 
     // this method is a bit too long but its just an example.. 
     Input i = createInput(); 

     B b = mock(B.class); 
     when(b.process(x)).thenReturn(expected); 

     A classUnderTest = createInstanceOfClassA(); 
     classUnderTest.setB(b); 

     Output o = classUnderTest.process(i); 

     assertEquals(o, expected); 
     verify(b).process(x); 
     verifyNoMoreInteractions(b); 
    } 

    @Test 
    public void smallerTest2(){ 
     B classUnderTest = createInstanceOfClassB(); 

     Output o = classUnderTest.process(x); 

     assertEquals(o, expected); 
    } 

} 
+0

+1 एक ही कक्षा में परीक्षणों को रखना (और आपके द्वारा किए गए टेस्ट क्लास का नामकरण) इससे कम संभावना है कि कोई व्यक्ति मूल परीक्षण और छोटे परीक्षणों के बीच गलती से कनेक्शन को तोड़ देगा। इसके लिए धन्यवाद। फिर भी मुझे यह जानने का कुछ स्वचालित तरीका याद आ रहा है कि छोटे परीक्षणों का अर्थ है कि बड़ा परीक्षण पास होगा। – mkorpela

+0

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

+0

@ हर्मे, मैं मूल परीक्षण को हटा नहीं सकता अगर यह ऐसी परिस्थिति में विफल हो सकता है जहां छोटे परीक्षण पास होंगे। – mkorpela

0

सभी मेरा सुझाव कर सकते हैं पुस्तक xUnit Test Patterns है। यदि कोई समाधान है तो यह वहां होना चाहिए।

0

theBigTestB पर निर्भरता याद आ रही है:

एक साथ यह सब लाना, आप की तरह कुछ हो सकता है। smallerTest1 मोजे B निर्भरता। smallerTest2 में आपको InputFromA पर नकल करना चाहिए।

आपने ऐसा निर्भरता ग्राफ क्यों बनाया है जैसा आपने किया था?

A एक B लेता है तो जब A::processInput, आप तो प्रक्रिया InputFromAB में पोस्ट करें।

निर्भरता मानचित्रण को बदलने के लिए बड़े परीक्षण और रिफैक्टर A और B रखें। टिप्पणियों के जवाब में

[संपादित करें]

@mkorpela, मेरा मुद्दा यह है कि कोड को देखकर और उनकी निर्भरता यह है कि आप छोटे परीक्षण कैसे बनाएं, इस बारे में एक विचार प्राप्त करना शुरू करते हैं। A पर B पर निर्भरता है। इसे process() को पूरा करने के लिए इसे B का process() का उपयोग करना होगा। इस वजह से, B पर A पर निर्भरता है।

+0

सबसे पहले इसका उद्देश्य केवल एक बहुत ही सरल उदाहरण है जिसका मैं लक्ष्य रख रहा हूं। मैं परीक्षण नियमों के लिए सामान्य नियम/उपकरण की पहचान करने की कोशिश कर रहा हूं ताकि मूल परीक्षण का अर्थ अभी भी वहां हो। बिगटेस्ट बी पर निर्भरता खो रहा है क्योंकि परीक्षण अधिक सार स्तर पर है (यह जानने की आवश्यकता नहीं है कि बी है लेकिन यह जानने की लागत यह नहीं है कि परीक्षण निष्पादित करने में अधिक समय लगेगा)। – mkorpela

+0

मैं सरल उदाहरणों के बारे में समझता हूं, लेकिन मेरा मुद्दा यह है कि 'बी' एक शून्य संदर्भ है जब आप 'systemUnderTest.process (i) 'निष्पादित करते हैं। यह नहीं चलेगा? इसके लिए आपको उस व्यवहार पर दो निकालने की विधि या कक्षा की आवश्यकता हो सकती है। उस व्यवहार का परीक्षण करने के लिए इसे निकालने की विधि या कक्षा की आवश्यकता हो सकती है। इसके अलावा, यदि कोई संभावना है कि दो परीक्षण पास हो जाएंगे और संभावना है कि बड़ा परीक्षण विफल हो जाएगा, तो आपको एक तीसरा परीक्षण करने की आवश्यकता है जो असफल व्यवहार का परीक्षण करे। – Gutzofter

+0

मेरी createSystemUnderTest() विधि सिस्टम अपरटेस्ट को प्रारंभ किए गए उदाहरण में सही ढंग से शुरू करेगी (मान लीजिए कि बी शून्य नहीं होगा)। यह अन्य परीक्षणों में उपयोग की जाने वाली वही विधि नहीं है। "यदि कोई संभावना है कि दो परीक्षण पास होंगे और एक संभावना है कि बड़ा परीक्षण असफल हो जाएगा, तो आपको एक तीसरा परीक्षण करने की आवश्यकता है जो असफल व्यवहार का परीक्षण करे।" - मुख्य बात जो मैं पूछ रहा हूं वह यह सुनिश्चित करना है कि छोटे परीक्षण मूल परीक्षण को कवर करेंगे। – mkorpela

संबंधित मुद्दे

 संबंधित मुद्दे