2011-04-06 17 views
5

के लिए वाईफाईमेनगर का मज़ाक उड़ाते हुए मैं कुछ कक्षाओं के लिए कुछ यूनिट परीक्षणों को लागू करने की कोशिश कर रहा हूं जो वाईफाईमेनगर और लौटाए गए स्कैनरियल्स पर भरोसा करते हैं। मैं जो करना चाहता हूं वह विभिन्न प्रकार की विभिन्न स्थितियों का परीक्षण करने के लिए प्राप्त स्कैनरसेट्स को नियंत्रित करने में सक्षम है।एंड्रॉइड यूनिट परीक्षण

दुर्भाग्य से वाईफाईमेनगर को सफलतापूर्वक नकल करने के लिए मेरे लिए काफी मुश्किल रहा है (हालांकि मुझे लगता है कि मैं अपने मॉक वाईफाई प्रबंधक में अपने कन्स्ट्रक्टर नल संदर्भों को पार कर सकता हूं)। यह केवल मेरी पहली समस्या होगी क्योंकि एक बार मेरे पास एक मॉक वाईफाई प्रबंधक है (यदि यह भी काम करता है!) मुझे सफलतापूर्वक अपना परीक्षण स्कैनरसेट्स बनाना होगा, जिसमें सार्वजनिक कन्स्ट्रक्टर नहीं है (कल्पना करें कि यह कहीं किसी फैक्ट्री द्वारा बनाई गई है)।

प्रश्न: इसके साथ कोई सार्वजनिक निर्माता नहीं है, क्या मैं इसे भी बढ़ा सकता हूं?

क्या मैं यह सब गलत कर रहा हूं? मुझे अक्सर एक विशिष्ट कार्य करने के तरीके के बारे में प्रश्न पूछे जाते हैं लेकिन वास्तव में वे गलत तरीके से एक अलग समस्या को हल करने की कोशिश कर रहे हैं, शायद यही मैं यहाँ कर रहा हूं?

मैं एंड्रॉइड के लिए बहुत नया हूं इसलिए इस कार्यक्षमता का नकल करना कम से कम कहने की कोशिश कर रहा है।

आपके इनपुट के लिए धन्यवाद!

संपादित करें: मुझे एक मॉक वाईफाई प्रबंधक को तुरंत चालू करने का समय भी है। वाईफाई मैनेजर के लिए कन्स्ट्रक्टर IWifiManager को एक प्रकार की उम्मीद कर रहा है जो एंड्रॉइड एसडीके में मौजूद नहीं है।

उत्तर

8

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

अपने परीक्षण के लिए आप प्रबंधक को दिल की सामग्री के लिए तैयार/नकली कर सकते हैं। उत्पादन के लिए आप एक ठोस उदाहरण में गुजरेंगे।

अपने कोड को बदलने के बारे में आपके बिंदु के संबंध में बस इसे टेस्ट करने योग्य बनाने के लिए गलत है। सबसे पहले आपको नीचे दिए गए पेपर में चर्चा के अनुसार भूमिकाओं का नकल नहीं करना चाहिए। अधिक जानकारी के लिए Google।

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

http://www.objectmentor.com/resources/articles/dip.pdf http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

+0

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

+0

@ ब्रायन हां। सबसे पहले आप एक ही स्थान पर वाईफाईमेनगर को स्वैप कर सकते हैं। क्या होता है जब संस्करण एक्स आता है और एपीआई में कोई अंतर होता है? आपको अपने कोडबेस में कई क्षेत्रों को बदलना होगा। मैं अधिक जानकारी के साथ अपना जवाब अपडेट कर रहा हूं। – Finglas

+0

आह हाँ, उन चीज़ों को अलग करें जो बदल सकते हैं। मेरे पास एंड्रॉइड एपीआई पर कोई नियंत्रण नहीं है जब तक कि मैं खुद को उस अमूर्तता से बचाता हूं। अच्छा निर्णय! – Brian

2

आप निजी रचनाकारों तक पहुंचने के लिए प्रतिबिंब का उपयोग करके ScanResult उदाहरण बनाने का प्रयास कर सकते हैं। कोड कुछ इस तरह दिख सकता है:

 try { 
      Constructor<ScanResult> ctor = ScanResult.class.getDeclaredConstructor(null); 
      ctor.setAccessible(true); 
      ScanResult sr = ctor.newInstance(null); 
      sr.BSSID = "foo"; 
      sr.SSID = "bar"; 
      // etc... 
     } catch (SecurityException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchMethodException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalArgumentException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InstantiationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

परीक्षण के अन्य तरीकों के लिए, मैं समय की सबसे ScanResult तरह उदाहरणों से जानकारी को परिवर्तित करने और केवल जानकारी मैं अपने ही वस्तुओं में की जरूरत है संपुटित। ये मैं कड़ी मेहनत करने के तरीके को खिलाता हूं। यह परीक्षण को आसान बनाता है क्योंकि आप वास्तविक स्कैनरसेट ऑब्जेक्ट्स पर भरोसा किए बिना इन मध्यवर्ती वस्तुओं को आसानी से बना सकते हैं।

+1

हर बार मुझे प्रतिबिंब का उपयोग करना पड़ता है, भगवान एक पिल्ला को मारता है। दुर्भाग्य से यह एकमात्र तरीका हो सकता है, कोड स्निपेट – Brian

0

मैं ScanResult वस्तु का निर्माण करने के लिए थोड़ी देर के लिए संघर्ष कर रहा है। मैंने उपरोक्त उस प्रतिबिंब दृष्टिकोण का सफलतापूर्वक उपयोग किया है।

किसी एक तरह से ScanResult वस्तु (या किसी अन्य वस्तु Parcelable इंटरफेस को लागू) यदि आप इस दृष्टिकोण का उपयोग कर सकते क्लोन करने के लिए खोज रहा है तो (मैं इसे सही एक इकाई परीक्षण में जाँच):

@RunWith(RobolectricTestRunner.class) 
@Config(manifest=Config.NONE) 
public class MovingAverageQueueTests { 
    @Test 
    public void parcelTest() { 
     Parcel parcel = Parcel.obtain(); 

     ScanResult sr = buildScanResult("01:02:03:04:05:06", 70); 

     parcel.writeValue(sr); 
     parcel.setDataPosition(0); // required after unmarshalling 
     ScanResult clone = (ScanResult)parcel.readValue(ScanResult.class.getClassLoader()); 
     parcel.recycle(); 

     assertThat(clone.BSSID, is(equalTo(sr.BSSID))); 
     assertThat(clone.level, is(equalTo(sr.level))); 
     assertThat(clone, is(not(sameInstance(sr)))); 
    } 

    private ScanResult buildScanResult(String mac, int level) { 
     Constructor<ScanResult> ctor = null; 
     ScanResult sr = null; 

     try { 
      ctor = ScanResult.class.getDeclaredConstructor(null); 
      ctor.setAccessible(true); 
      sr = ctor.newInstance(null); 

      sr.BSSID = mac; 
      sr.level = level; 

     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } catch (InstantiationException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      e.printStackTrace(); 
     } 

     return sr; 
    } 
} 

और के लिए के रूप में प्रदर्शन, इस भोली जांच:

@Test 
public void buildVsClonePerformanceTest() { 
    ScanResult sr = null; 

    long start = System.nanoTime(); 
    for (int i = 0; i < 1000000; i++) { 
     sr = buildScanResult("01:02:03:04:05:06", 70); 
    } 
    long elapsedNanos = System.nanoTime() - start; 

    LOGGER.info("buildScanResult: " + elapsedNanos); 

    start = System.nanoTime(); 
    for (int i = 0; i < 1000000; i++) { 
     sr = cloneScanResult(sr); 
    } 
    elapsedNanos = System.nanoTime() - start; 

    LOGGER.info("cloneScanResult: " + elapsedNanos); 
} 

दिखाया इन परिणामों:

अक्टू 26, वर्ष 2016 15:25:19 com.example.neutrino.maze.MovingAverageQueueTests buildVsClonePerformanceTest जानकारी: buildScanResult: 202,072,179 अक्टू 26, वर्ष 2016 15:25:21 com.example.neutrino.maze.MovingAverageQueueTests buildVsClonePerformanceTest जानकारी: cloneScanResult:

तो इस तरह से क्लोनिंग 10 गुना कम भी प्रतिबिंब के साथ उदाहरण बनाने की तुलना में प्रभावी है। मुझे पता है कि यह परीक्षण मजबूत नहीं है क्योंकि संकलन के दौरान अनुकूलन किया जाता है ... हालांकि दस का कारक कम करना मुश्किल है। मैंने 10 के पुनरावृत्तियों का भी परीक्षण किया और फिर कारक भी 100 था! सिर्फ तुम्हारी जानकारी के लिए।

पीएस पार्सल .obtain() और पार्सल से बाहर पार्सल। रीसायकल

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