2009-08-04 18 views
38

कंसुरेंसी परीक्षण चलाने के लिए जूनिट का उपयोग कैसे करें?समवर्ती इकाई परीक्षण कैसे चलाएं?

चलो कहते हैं कि मैं एक वर्ग

public class MessageBoard 
{ 
    public synchronized void postMessage(String message) 
    { 
     .... 
    } 

    public void updateMessage(Long id, String message) 
    { 
     .... 
    } 
} 

मैं समवर्ती इस postMessage को मल्टीपल एक्सेस का परीक्षण करने के वान करते हैं। इस पर कोई सलाह? मैं अपने सभी सेटर फ़ंक्शंस (या किसी भी विधि जिसमें निर्माण/अपडेट/डिलीट ऑपरेशन शामिल है) के खिलाफ इस तरह के समवर्ती परीक्षण को चलाने की इच्छा है।

उत्तर

18

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

शायद आपको PMD जैसे कुछ स्थिर विश्लेषण टूल देखना चाहिए, जो यह निर्धारित कर सकते हैं कि आप सिंक्रनाइज़ेशन का उपयोग कैसे कर रहे हैं और उपयोग की समस्याओं की पहचान कैसे कर सकते हैं।

+3

+1 स्थिर कोड विश्लेषक के उपयोग का सुझाव देने के लिए। एक Google खोज कई संभावनाओं को प्रकट करती है [जावा समरूपता स्थिर विश्लेषण]। –

+0

http://channel9.msdn.com/shows/Going+Deep/CHESS-An-Automated-Concurrency-Testing-Tool/ – inf3rno

8

आप केवल समवर्ती बग की उपस्थिति साबित कर सकते हैं, उनकी अनुपस्थिति नहीं।

हालांकि आप एक विशेष परीक्षण धावक लिख सकते हैं जो कई समवर्ती धागे को जन्म देता है और फिर आपके @ टेस्ट एनोटेटेड विधियों को कॉल करता है।

+16

> (परीक्षण के साथ) "आप केवल समवर्ती कीड़े की उपस्थिति, नहीं उनकी अनुपस्थिति साबित कर सकते हैं। " सामान्य अर्थ में, यह गैर-समवर्ती बग के लिए भी सही है। – Thilo

+4

यह कुछ हद तक सच है, लेकिन पारंपरिक इकाई परीक्षण के साथ आप * विशिष्ट * बग की (वर्तमान) अनुपस्थिति साबित कर सकते हैं। समेकन के मुद्दों के परीक्षण के दौरान आपको इतना भी नहीं मिलता है। –

0

TestNG जावा में समवर्ती परीक्षण के लिए समर्थन है। यह article वर्णन करता है कि इसका उपयोग कैसे किया जा सकता है और testng साइट पर दस्तावेज़ हैं।

सुनिश्चित नहीं हैं कि अगर आप एक ही समय में हालांकि

0

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

हालांकि, अगर आप इसे पूर्ण इंस्टॉल और पूर्ण वातावरण के अलावा किसी स्तर पर करना चाहते हैं तो आप अपनी वस्तु को एक अलग धागे में बनाकर जूनिट में ऐसा कर सकते हैं, फिर अपने ऑब्जेक्ट को आग लगने वाले बहुत सारे थ्रेड बनाएं और जब तक यह पूरा नहीं हो जाता है तब तक मुख्य धागे को अवरुद्ध करें। यदि आप इसे सही नहीं पाते हैं तो यह दृष्टिकोण परीक्षणों को अंतःस्थापित कर सकता है।

+0

दुर्भाग्यवश, यह दृष्टिकोण बग को उजागर करने में बहुत अप्रभावी है, क्योंकि बार-बार एक ही परीक्षण चलने से आमतौर पर एक ही थ्रेड को ओवरलेविंग का परीक्षण किया जाएगा। –

+0

आप यह कैसे करेंगे? ग्राहक परीक्षणों का प्रतिनिधित्व करने वाले सिस्टम परीक्षणों का एक व्यापक सूट उस बग को मिलेगा जो ग्राहक देखेंगे। –

7

.NET में, TypeMock Racer या Microsoft CHESS जैसे टूल हैं जो विशेष रूप से इकाई परीक्षण समरूपता के लिए डिज़ाइन किए गए हैं। इन औजारों को न केवल मल्टीथ्रेडिंग बग जैसे डेडलॉक्स मिलते हैं, बल्कि आपको थ्रेड इंटरलीव्स का सेट भी देते हैं जो त्रुटियों को पुन: उत्पन्न करते हैं।

मुझे लगता है कि जावा दुनिया के लिए कुछ समान है।

1

अपने उदाहरण में postMessage() विधि सिंक्रनाइज़ है, तो आप वास्तव में एक भी वी एम के भीतर से किसी भी संगामिति प्रभाव नहीं देखेंगे, लेकिन आप सिंक्रनाइज़ संस्करण के प्रदर्शन का मूल्यांकन करने में सक्षम हो सकता है।

आपको विभिन्न वीएम में एक ही समय में परीक्षण कार्यक्रम की कई प्रतियां चलाने की आवश्यकता होगी। आप

का उपयोग कर सकते हैं यदि आप इसे करने के लिए अपना परीक्षण ढांचा नहीं प्राप्त कर सकते हैं तो आप अपने स्वयं के कुछ वीएम लॉन्च कर सकते हैं। प्रक्रिया बिल्डर सामान रास्तों और whatnot के साथ एक दर्द है, लेकिन यहां एक सामान्य स्केच है:

Process running[] = new Process[5]; 
for (int i = 0; i < 5; i++) { 
ProcessBuilder b = new ProcessBuilder("java -cp " + getCP() + " MyTestRunner"); 
running[i] = b.start(); 
} 

for(int i = 0; i < 5; i++) { 
running[i].waitFor(); 
} 

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

public void testMesageBoard() { 
final MessageBoard b = new MessageBoard(); 

int n = 5; 
Thread T[] = new Thread[n]; 
for (int i = 0; i < n; i++) { 
    T[i] = new Thread(new Runnable() { 
    public void run() { 
    for (int j = 0; j < maxIterations; j++) { 
     Thread.sleep(random.nextInt(50)); 
     b.postMessage(generateMessage(j)); 
     verifyContent(j); // put some assertions here 
    } 
    } 
    }); 

    PerfTimer.start(); 
    for (Thread t : T) { 
    t.start(); 
    } 

    for (Thread t : T) { 
    t.join(); 
    } 
    PerfTimer.stop(); 
    log("took: " + PerfTimer.elapsed()); 
} 
}**strong text** 
1

परीक्षण समवर्ती बग असंभव है; आपको केवल इनपुट/आउटपुट जोड़े को प्रमाणित करने की आवश्यकता नहीं है, लेकिन आपको उन स्थितियों में स्थिति को सत्यापित करना होगा जो आपके परीक्षणों के दौरान हो सकते हैं या नहीं भी हो सकते हैं। दुर्भाग्य से जुनीट ऐसा करने के लिए सुसज्जित नहीं है।

+1

शायद वे यह असंभव है ताकि वे इसे http://channel9.msdn.com/shows/Going+Deep/CHESS-An-Automated-Concurrency-Testing-Tool/ – inf3rno

15

मैं MultithreadedTC का उपयोग करने की सलाह दूंगा - समेकन मास्टर द्वारा लिखित Bill Pugh (और Nat Ayewah)। उनके overview से उद्धरण:

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

इस ढांचे आप निर्धारणात्मक अलग परीक्षण

1

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

documentation के जुनीट एकीकरण खंड देखें।

Btw, मैं पर एक डेवलपर ने कहा कि परियोजना :)

+0

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

+0

निश्चित (और कम से कम 15 वर्ण टाइप करने के लिए मजबूर) – Toby

1

ActiveTestSuite में देखने का प्रयास जो JUnit के साथ जहाज। यह समवर्ती कई JUnit परीक्षण शुरू कर सकते हैं:

public static Test suite() 
{ 
    TestSuite suite = new ActiveTestSuite(); 
    suite.addTestSuite(PostMessageTest.class); 
    suite.addTestSuite(PostMessageTest.class); 
    suite.addTestSuite(PostMessageTest.class); 
    suite.addTestSuite(PostMessageTest.class); 
    suite.addTestSuite(PostMessageTest.class); 
    return suite; 
} 

ऊपर ही JUnit परीक्षण वर्ग समानांतर में 5 बार चलेंगे। यदि आप अपने पैरालेल परीक्षणों में भिन्नता चाहते थे, तो बस एक अलग वर्ग बनाएं।

5

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

Mycila work on JUnit ConcurrentJunitRunner and ConcurrentSuite बहुत दिलचस्प है। लेख नवीनतम जीए रिलीज की तुलना में थोड़ा पुराना प्रतीत होता है, मेरे उदाहरणों में मैं अद्यतन उपयोग दिखाऊंगा।

import com.mycila.junit.concurrent.ConcurrentJunitRunner; 
import com.mycila.junit.concurrent.Concurrency; 

@RunWith(ConcurrentJunitRunner.class) 
@Concurrency(6) 
public final class ATest { 
... 

तुम भी सभी परीक्षण कक्षाओं समवर्ती चला सकते हैं::

निम्नलिखित की तरह एक परीक्षण वर्ग टिप्पणी करना 6 के एक संगामिति स्तर के साथ समवर्ती परीक्षण तरीकों पर अमल करने, का कारण होगा

import com.mycila.junit.concurrent.ConcurrentSuiteRunner; 

@RunWith(ConcurrentSuiteRunner.class) 
@Suite.SuiteClasses({ATest.class, ATest2.class, ATest3.class}) 
public class MySuite { 
} 

Maven dependency है:

<dependency> 
    <groupId>com.mycila</groupId> 
    <artifactId>mycila-junit</artifactId> 
    <version>1.4.ga</version> 
</dependency> 

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

@Test 
public final void runConcurrentMethod() throws InterruptedException { 
    ExecutorService exec = Executors.newFixedThreadPool(16); 
    for (int i = 0; i < 10000; i++) { 
     exec.execute(new Runnable() { 
      @Override 
      public void run() { 
       concurrentMethod(); 
      } 
     }); 
    } 
    exec.shutdown(); 
    exec.awaitTermination(50, TimeUnit.SECONDS); 
} 

private void concurrentMethod() { 
    //do and assert something 
} 

दूसरों के रूप में बताया गया है, सच है कि आप कभी नहीं जानते कि एक संगामिति बग ऊपर या नहीं दिखाना चाहते हो सकता है, लेकिन हजारों की दस, या के एक संगामिति के साथ हजारों फांसी के सौ, के साथ कह 16, सांख्यिकी है तुम्हारे पक्ष में।

+0

एफवाईआई, आपके घर के समाधान के आधार पर, आप [इस आलेख] के समान कस्टम जुनीट नियम को आसानी से कार्यान्वित कर सकते हैं (http://www.codeaffine.com/2013/04/ 10/रनिंग-जूनिट-टेस्ट-बार-बार-बिना-लूप /) बीटीडब्ल्यू मैं अब भी ऐसा करने की कोशिश कर रहा हूं :) – Yura

0

तुम भी HavaRunner कोशिश कर सकते हैं। यह डिफ़ॉल्ट रूप से समानांतर में परीक्षण चलाता है।

0

आप IMUnit देख सकते हैं। यह जुनीट के साथ संगत है।

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