मैं एक जावा प्रोजेक्ट पर काम कर रहा हूं। मैं इकाई परीक्षण के लिए नया हूं। जावा कक्षाओं में निजी तरीकों को जांचने का सबसे अच्छा तरीका क्या है?
मैं एक जावा प्रोजेक्ट पर काम कर रहा हूं। मैं इकाई परीक्षण के लिए नया हूं। जावा कक्षाओं में निजी तरीकों को जांचने का सबसे अच्छा तरीका क्या है?
जवाबों:
आप आम तौर पर सीधे निजी तरीकों का परीक्षण नहीं करते हैं। चूंकि वे निजी हैं, इसलिए उन्हें कार्यान्वयन विस्तार पर विचार करें। कोई भी कभी भी उनमें से एक को कॉल करने वाला नहीं है और यह उम्मीद करता है कि यह एक विशेष तरीके से काम करेगा।
आपको इसके बजाय अपने सार्वजनिक इंटरफ़ेस का परीक्षण करना चाहिए। यदि आपके निजी तरीकों को कॉल करने वाले तरीके आपकी अपेक्षा के अनुसार काम कर रहे हैं, तो आप विस्तार से मानते हैं कि आपके निजी तरीके सही तरीके से काम कर रहे हैं।
सामान्य तौर पर, मैं इससे बचूंगा। यदि आपकी निजी पद्धति इतनी जटिल है कि उसे एक अलग इकाई परीक्षण की आवश्यकता है, तो इसका मतलब अक्सर यह होता है कि वह अपनी कक्षा के योग्य है। यह आपको इसे एक तरह से लिखने के लिए प्रोत्साहित कर सकता है जो पुन: प्रयोज्य है। फिर आपको नई कक्षा का परीक्षण करना चाहिए और अपने पुराने वर्ग में सार्वजनिक इंटरफ़ेस को कॉल करना चाहिए।
दूसरी ओर, कभी-कभी कार्यान्वयन विवरणों को अलग-अलग कक्षाओं में विभाजित करने से जटिल इंटरफेस के साथ कक्षाएं होती हैं, बहुत सारे डेटा पुराने और नए वर्ग के बीच गुजर रहे हैं, या एक डिज़ाइन के लिए जो ओओपी दृष्टिकोण से अच्छा लग सकता है, लेकिन ऐसा नहीं करता है समस्या डोमेन से आने वाले अंतर्ज्ञान से मेल खाते हैं (उदाहरण के लिए निजी तरीकों का परीक्षण करने से बचने के लिए एक मूल्य मॉडल को दो टुकड़ों में विभाजित करना बहुत सहज नहीं है और कोड को बनाए रखने / बढ़ाते समय बाद में समस्याओं का कारण बन सकता है)। आप "ट्विन क्लासेस" नहीं चाहते हैं, जो हमेशा एक साथ बदली जाती हैं।
जब एनकैप्सुलेशन और टेस्टिबिलिटी के बीच एक विकल्प का सामना करना पड़ता है, तो मैं दूसरे के लिए जाना चाहता हूं। एक अच्छा OOP डिज़ाइन जो सही ढंग से काम नहीं करता है, की तुलना में सही कोड (यानी सही आउटपुट का उत्पादन) करना अधिक महत्वपूर्ण है, क्योंकि यह पर्याप्त रूप से परीक्षण नहीं किया गया था। जावा में, आप बस विधि को "डिफ़ॉल्ट" एक्सेस दे सकते हैं और यूनिट टेस्ट को उसी पैकेज में डाल सकते हैं। यूनिट परीक्षण आपके द्वारा विकसित किए जा रहे पैकेज का केवल एक हिस्सा हैं, और परीक्षण और कोड के बीच निर्भरता होना ठीक है जो परीक्षण किया जा रहा है। इसका मतलब है कि जब आप कार्यान्वयन बदलते हैं, तो आपको अपने परीक्षणों को बदलने की आवश्यकता हो सकती है, लेकिन यह ठीक है - कार्यान्वयन के प्रत्येक परिवर्तन के लिए कोड का पुन: परीक्षण करना आवश्यक है, और यदि परीक्षणों को ऐसा करने के लिए संशोधित करने की आवश्यकता है, तो आप बस करते हैं यह।
सामान्य तौर पर, एक वर्ग एक से अधिक इंटरफ़ेस पेश कर सकता है। उपयोगकर्ताओं के लिए एक इंटरफ़ेस है, और अनुरक्षकों के लिए एक इंटरफ़ेस है। दूसरा यह सुनिश्चित करने के लिए अधिक उजागर कर सकता है कि कोड पर्याप्त रूप से परीक्षण किया गया है। यह एक निजी पद्धति पर एक इकाई परीक्षण होना जरूरी नहीं है - यह हो सकता है, उदाहरण के लिए, लॉगिंग। लॉगिंग "इनकैप्सुलेशन को तोड़ता है", लेकिन हम अभी भी इसे करते हैं, क्योंकि यह बहुत उपयोगी है।
निजी तरीकों का परीक्षण उनकी जटिलता पर निर्भर करेगा; कुछ एक लाइन निजी विधियाँ वास्तव में परीक्षण के अतिरिक्त प्रयास (यह सार्वजनिक विधियों के बारे में भी कहा जा सकता है) को वारंट नहीं करेंगी, लेकिन कुछ निजी विधियाँ सार्वजनिक विधियों की तरह ही जटिल हो सकती हैं, और सार्वजनिक इंटरफ़ेस के माध्यम से परीक्षण करना कठिन हो सकता है।
मेरी पसंदीदा तकनीक निजी विधि पैकेज को निजी बनाना है, जो एक ही पैकेज में एक इकाई परीक्षण तक पहुंच की अनुमति देगा, लेकिन यह अभी भी अन्य सभी कोड से समझाया जाएगा। यह (संभवतः) जटिल तर्क के सभी भागों को कवर करने के लिए सार्वजनिक विधि परीक्षण पर भरोसा करने के बजाय सीधे निजी विधि तर्क का परीक्षण करने का लाभ देगा।
यदि इसे Google अमरूद लाइब्रेरी में @VoiceForTesting एनोटेशन के साथ जोड़ा जाता है, तो आप इस पैकेज को केवल निजी तौर पर परीक्षण के लिए दृश्यमान तरीके से चिह्नित कर रहे हैं और इसे किसी अन्य वर्ग द्वारा नहीं बुलाया जाना चाहिए।
इस तकनीक के विरोधियों का तर्क है कि इससे एनकैप्सुलेशन टूट जाएगा और एक ही पैकेज में कोड करने के लिए निजी तरीके खुलेंगे। जबकि मैं मानता हूं कि यह एनकैप्सुलेशन को तोड़ता है और अन्य वर्गों के लिए निजी कोड खोलता है, मेरा तर्क है कि सख्त तर्क से परीक्षण जटिल तर्क अधिक महत्वपूर्ण है और पैकेज निजी तरीकों का उपयोग नहीं करना जो स्पष्ट रूप से केवल परीक्षण के लिए दृश्यमान हैं, डेवलपर्स की जिम्मेदारी होनी चाहिए कोड बेस का उपयोग करना और बदलना।
परीक्षण से पहले निजी विधि:
private int add(int a, int b){
return a + b;
}
परीक्षण के लिए तैयार पैकेज निजी विधि:
@VisibleForTesting
int add(int a, int b){
return a + b;
}
नोट: एक ही पैकेज में परीक्षण डालना उन्हें एक ही भौतिक फ़ोल्डर में डालने के बराबर नहीं है। अपने मुख्य कोड और परीक्षण कोड को अलग-अलग भौतिक फ़ोल्डर संरचनाओं में अलग करना सामान्य रूप से अच्छा अभ्यास है लेकिन यह तकनीक तब तक काम करेगी जब तक कि कक्षाओं को एक ही पैकेज में परिभाषित नहीं किया जाता है।
यदि आप बाहरी API का उपयोग नहीं कर सकते हैं या नहीं करना चाहते हैं, तो आप प्रतिबिंब का उपयोग करके निजी तरीकों तक पहुंचने के लिए अभी भी शुद्ध मानक JDK API का उपयोग कर सकते हैं। यहाँ एक उदाहरण है
MyObject obj = new MyObject();
Method privateMethod = MyObject.class.getDeclaredMethod("getFoo", null);
privateMethod.setAccessible(true);
String returnValue = (String) privateMethod.invoke(obj, null);
System.out.println("returnValue = " + returnValue);
Java ट्यूटोरियल http://docs.oracle.com/javase/tutorial/reflect/ या Java API http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/package-summary चेक करें । अधिक जानकारी के लिए html ।
जैसा कि @kij ने अपने जवाब में बताया कि ऐसे समय होते हैं जब प्रतिबिंब का उपयोग करने वाला एक सरल समाधान एक निजी विधि का परीक्षण करने के लिए वास्तव में अच्छा होता है।
यूनिट टेस्ट केस का मतलब कोड की यूनिट का परीक्षण करना है। इसका मतलब इंटरफ़ेस का परीक्षण करना नहीं है क्योंकि यदि आप इंटरफ़ेस का परीक्षण कर रहे हैं, तो इसका मतलब यह नहीं है कि आप कोड की इकाई का परीक्षण कर रहे हैं। यह एक ब्लैक बॉक्स टेस्टिंग की तरह हो जाता है। इसके अलावा, इंटरफ़ेस स्तर पर मुद्दों को निर्धारित करने की तुलना में सबसे छोटी इकाई स्तर पर मुद्दों को ढूंढना बेहतर है और फिर यह डिबग करने की कोशिश करना कि कौन सा टुकड़ा काम नहीं कर रहा था। इसलिए, इकाई परीक्षण मामले को उनके दायरे के बावजूद परीक्षण किया जाना चाहिए। निम्नलिखित निजी तरीकों का परीक्षण करने का एक तरीका है।
यदि आप जावा का उपयोग कर रहे हैं, तो आप jmockit का उपयोग कर सकते हैं जो परीक्षण के लिए कक्षा के किसी भी निजी तरीके को कॉल करने के लिए Deencapsulation.invoke प्रदान करता है। यह अंततः इसे कॉल करने के लिए प्रतिबिंब का उपयोग करता है लेकिन इसके चारों ओर एक अच्छा आवरण प्रदान करता है। ( https://code.google.com/p/jmockit/ )
सबसे पहले, जैसा कि अन्य लेखकों ने सुझाव दिया है: दो बार सोचें कि क्या आपको वास्तव में निजी पद्धति का परीक्षण करने की आवश्यकता है। और यदि ऐसा है तो, ...
.NET में आप इसे "आंतरिक" विधि में परिवर्तित कर सकते हैं, और अपने यूनिट टेस्ट प्रोजेक्ट के लिए पैकेज को " इंटरनलविजुअल " बना सकते हैं।
जावा में आप परीक्षण किए जाने वाले वर्ग में ही परीक्षण लिख सकते हैं और आपके परीक्षण तरीकों को निजी तरीकों को भी कॉल करने में सक्षम होना चाहिए। मेरे पास वास्तव में बड़ा जावा अनुभव नहीं है, इसलिए शायद यह सबसे अच्छा अभ्यास नहीं है।
धन्यवाद।
मैं आमतौर पर ऐसे तरीकों को संरक्षित करता हूं। मान लें कि आपकी कक्षा निम्न में है:
src/main/java/you/Class.java
आप एक परीक्षण वर्ग बना सकते हैं:
src/test/java/you/TestClass.java
अब आपके पास संरक्षित तरीकों तक पहुंच है और उन्हें (JUnit या TestNG वास्तव में कोई फर्क नहीं पड़ता) यूनिट का परीक्षण कर सकते हैं, फिर भी आप इन तरीकों को उन कॉलरों से रखते हैं जिन्हें आप नहीं चाहते थे।
ध्यान दें कि यह एक मावेन-शैली के स्रोत के पेड़ की अपेक्षा करता है।
यदि आपको वास्तव में निजी विधि का परीक्षण करने की आवश्यकता है, तो जावा के साथ मेरा मतलब है, आप उपयोग कर सकते हैं fest assert
और / या fest reflect
। यह प्रतिबिंब का उपयोग करता है।
लाइब्रेरी को मावेन के साथ आयात करें (दिए गए संस्करण मेरे विचार से सबसे अंतिम नहीं हैं) या इसे सीधे आपके क्लासपाथ में आयात करें:
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-reflect</artifactId>
<version>1.2</version>
</dependency>
एक उदाहरण के रूप में, यदि आपके पास 'myPStreetMethod' नाम की एक निजी पद्धति के साथ 'MyClass' नाम का एक वर्ग है, जो एक स्ट्रिंग को पैरामीटर के रूप में ले जाता है, तो इसका मान 'यह कूल टेस्टिंग है!'
import static org.fest.reflect.core.Reflection.method;
...
MyClass objectToTest;
@Before
public void setUp(){
objectToTest = new MyClass();
}
@Test
public void testPrivateMethod(){
// GIVEN
String myOriginalString = "toto";
// WHEN
method("myPrivateMethod").withParameterTypes(String.class).in(objectToTest).invoke(myOriginalString);
// THEN
Assert.assertEquals("this is cool testing !", myOriginalString);
}
यह लाइब्रेरी आपको किसी मॉक द्वारा किसी भी सेम गुण (चाहे वे निजी हों और कोई बसने वाले नहीं लिखे गए हैं) को बदलने में सक्षम बनाता है, और मॉकिटो या किसी अन्य नकली ढांचे के साथ इसका उपयोग करना वास्तव में अच्छा है। इस समय आपके पास केवल एक चीज है जो यह नहीं जानती है (अगले संस्करणों में यह बेहतर होगा या नहीं) यह लक्ष्य क्षेत्र / विधि का नाम है जिसे आप हेरफेर करना चाहते हैं, और इसके हस्ताक्षर।
मैं आमतौर पर C # में जो करता हूं वह मेरे तरीकों को सुरक्षित बनाता है और निजी नहीं। यह थोड़ा कम निजी एक्सेस संशोधक है, लेकिन यह उन सभी वर्गों से विधि को छिपाता है जो परीक्षण के तहत कक्षा से विरासत में नहीं आते हैं।
public class classUnderTest
{
//this would normally be private
protected void methodToTest()
{
//some code here
}
}
कोई भी वर्ग जो सीधे classUnderTest से विरासत में नहीं आता है, उसे इस बात का कोई अंदाजा नहीं है कि MethodToTest भी मौजूद है। अपने परीक्षण कोड में, मैं एक विशेष परीक्षण वर्ग बना सकता हूं जो इस पद्धति तक विस्तारित और पहुंच प्रदान करता है ...
class TestingClass : classUnderTest
{
public void methodToTest()
{
//this returns the method i would like to test
return base.methodToTest();
}
}
यह वर्ग केवल मेरे परीक्षण प्रोजेक्ट में मौजूद है। इसका एकमात्र उद्देश्य इस एकल विधि तक पहुंच प्रदान करना है। यह मुझे उन स्थानों तक पहुंचने की अनुमति देता है जो अधिकांश अन्य वर्गों के पास नहीं हैं।
protected
सार्वजनिक एपीआई का हिस्सा है और उसी सीमाओं को लागू करता है (कभी नहीं बदला जा सकता है, दस्तावेज होना चाहिए, ...)। C # में आप internal
एक साथ उपयोग कर सकते हैं InternalsVisibleTo
।
यदि आप अपनी यूनिट का परीक्षण जिस कक्षा में कर रहे हैं, उस कक्षा में आप अपने यूनिट टेस्ट को आसानी से कर सकते हैं, तो आप आसानी से निजी तरीकों का परीक्षण कर सकते हैं। TestNG का उपयोग करते हुए आपकी इकाई परीक्षणों को सार्वजनिक स्थैतिक आंतरिक वर्गों को इस तरह @Test के साथ एनोटेट किया जाना चाहिए:
@Test
public static class UserEditorTest {
public void test_private_method() {
assertEquals(new UserEditor().somePrivateMethod(), "success");
}
}
चूंकि यह एक आंतरिक वर्ग है, इसलिए निजी पद्धति को बुलाया जा सकता है।
मेरे परीक्षण मावेन से चलाए जाते हैं और यह स्वचालित रूप से इन परीक्षण मामलों को ढूंढता है। यदि आप सिर्फ एक वर्ग का परीक्षण करना चाहते हैं तो आप कर सकते हैं
$ mvn test -Dtest=*UserEditorTest
स्रोत: http://www.ninthavenue.com.au/how-to-unit-test-pStreet-methods