खोज…


परिचय

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

वाक्य - विन्यास

  • निष्क्रिय संसाधन
  • स्ट्रिंग getName () - आइडलिंग रिसोर्स का नाम देता है (जिसका उपयोग लॉगिंग और रजिस्ट्रेशन की बेकरारी के लिए किया जाता है)।
  • बूलियन isIdleNow () - यदि संसाधन वर्तमान में निष्क्रिय है तो सही है।
  • void registerIdleTransitionCallback (IdlingResource.ResourceCallback callback) - संसाधन के साथ दिए गए IdlingResource.ResourceCallback को पंजीकृत करता है।

टिप्पणियों

न्याय नियम:

जैसा कि आप MockWebServer उदाहरण में देख सकते हैं और ActivityTestRule वे JUnit नियमों की श्रेणी में आते हैं, जो आप को परिभाषित जो तब प्रत्येक परीक्षा के लिए मार डाला जाना चाहिए अपने आप बना सकते हैं अपने व्यवहार @see: https://github.com/junit-team/junit4/ wiki / नियम

Appium

पैरामीटर

चूंकि पैरामीटर में कुछ समस्याएं हैं, जब तक कि दस्तावेज़ बग को हल नहीं किया जाता है:

पैरामीटर विवरण
कक्षा गतिविधि कौन सी गतिविधि शुरू करनी है
initialTouchMode गतिविधि को प्रारंभ में टच मोड में रखा जाना चाहिए: https://android-developers.blogspot.de/2008/12/touch-mode.html
launchActivity सच है अगर गतिविधि को एक बार परीक्षण विधि के अनुसार लॉन्च किया जाना चाहिए। यह पहले के पहले विधि से पहले लॉन्च किया जाएगा, और अंतिम के बाद विधि के बाद समाप्त किया जाएगा।

मॉकवेबसर उदाहरण

यदि आपकी गतिविधियों, अंशों और UI के लिए कुछ पृष्ठभूमि प्रसंस्करण की आवश्यकता होती है, तो उपयोग करने के लिए एक अच्छी चीज है एक MockWebServer जो एक Android डिवाइस पर स्थानीय चलाता है जो आपके UI के लिए एक बंद और परीक्षण योग्य वातावरण लाता है।

https://github.com/square/okhttp/tree/master/mockwebserver

पहला कदम ग्रेडेल डिपेंडेंसी सहित है:

testCompile 'com.squareup.okhttp3:mockwebserver:(insert latest version)'

अब मॉक सर्वर को चलाने और उपयोग करने के चरण हैं:

  • नकली सर्वर ऑब्जेक्ट बनाएँ
  • इसे विशिष्ट पते और पोर्ट पर शुरू करें (आमतौर पर लोकलहोस्ट: पोर्टनंबर)
  • विशिष्ट अनुरोधों के लिए प्रतिक्रियाएँ
  • परीक्षण शुरू करें

यह अच्छी तरह से mockwebserver के github पृष्ठ में समझाया गया है, लेकिन हमारे मामले में हम सभी परीक्षणों के लिए कुछ अच्छा और पुन: प्रयोज्य चाहते हैं, और JUnit नियम अच्छी तरह से यहां आ जाएंगे:

/**
 *JUnit  rule that starts and stops a mock web server for test runner
*/
 public class MockServerRule extends UiThreadTestRule {

 private MockWebServer mServer;

 public static final int MOCK_WEBSERVER_PORT = 8000;

    @Override
    public Statement apply(final Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                startServer();
                try {
                    base.evaluate();
                } finally {
                    stopServer();
                }
            }
        };
    }

    /**
     * Returns the started web server instance
     *
     * @return mock server
     */
    public MockWebServer server() {
        return mServer;
    }

    public void startServer() throws IOException, NoSuchAlgorithmException {
        mServer = new MockWebServer();
        try {
            mServer(MOCK_WEBSERVER_PORT);
        } catch (IOException e) {
            throw new IllegalStateException(e,"mock server start issue");
        }
    }

    public void stopServer() {
        try {
            mServer.shutdown();
        } catch (IOException e) {
            Timber.e(e, "mock server shutdown error”);
        }
    }
}

अब मान लेते हैं कि हमारे पास पिछले उदाहरण की तरह ही सटीक गतिविधि है, बस इस मामले में जब हम बटन ऐप को धक्का देते हैं तो उदाहरण के लिए नेटवर्क से कुछ प्राप्त होगा: https://someapi.com/name

यह कुछ टेक्स्ट स्ट्रिंग लौटाएगा जिसे स्नैकबार टेक्स्ट जैसे NAME + टेक्स्ट में टाइप किया जाएगा।

/**
* Testing of the snackbar activity with networking.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
    //espresso rule which tells which activity to start
    @Rule
    public final ActivityTestRule<SnackbarActivity> mActivityRule = 
        new ActivityTestRule<>(SnackbarActivity.class, true, false);

    //start mock web server
    @Rule
    public final MockServerRule mMockServerRule = new MockServerRule();

    @Override
    public void tearDown() throws Exception {
       //same as previous example
    }
    
    @Override
    public void setUp() throws Exception {
       //same as previous example

       **//IMPORTANT:** point your application to your mockwebserver endpoint e.g.
       MyAppConfig.setEndpointURL("http://localhost:8000");
    }
    
    /**
    *Test methods should always start with "testXYZ" and it is a good idea to 
    *name them after the intent what you want to test
    **/
    @Test
    public void testSnackbarIsShown() {
        //setup mockweb server
        mMockServerRule.server().setDispatcher(getDispatcher());

        mActivityRule.launchActivity(null);
        //check is our text entry displayed and enter some text to it
        String textToType="new snackbar text";
        onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
        //we check is our snackbar showing text from mock webserver plus the one we typed
        onView(withId(R.id.textEntry)).perform(typeText("JazzJackTheRabbit" + textToType));
        //click the button to show the snackbar
        onView(withId(R.id.shownSnackbarBtn)).perform(click());
        //assert that a view with snackbar_id with text which we typed and is displayed
        onView(allOf(withId(android.support.design.R.id.snackbar_text), 
        withText(textToType))) .check(matches(isDisplayed()));
    }
    
     /**
     *creates a mock web server dispatcher with prerecorded requests and responses
     **/
    private Dispatcher getDispatcher() {
        final Dispatcher dispatcher = new Dispatcher() {
            @Override
            public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
                if (request.getPath().equals("/name")){
                    return new MockResponse().setResponseCode(200)
                            .setBody("JazzJackTheRabbit");
                }
                throw new IllegalStateException("no mock set up for " + request.getPath());
            }
        };
        return dispatcher;
    }

मैं आपको किसी प्रकार के बिल्डर में डिस्पैचर को लपेटने का सुझाव दूंगा ताकि आप आसानी से चेन कर सकें और अपनी स्क्रीन के लिए नई प्रतिक्रियाएं जोड़ सकें। जैसे

 return newDispatcherBuilder()
            .withSerializedJSONBody("/authenticate", Mocks.getAuthenticationResponse())
            .withSerializedJSONBody("/getUserInfo", Mocks.getUserInfo())
            .withSerializedJSONBody("/checkNotBot", Mocks.checkNotBot());

IdlingResource

निष्क्रिय संसाधनों की शक्ति कुछ ऐप के प्रसंस्करण (नेटवर्किंग, गणना, एनिमेशन, आदि) का इंतजार करने के लिए sleep() साथ समाप्त करने के लिए नहीं है sleep() , जो कि चंचलता लाता है और / या परीक्षणों को आगे बढ़ाता है। आधिकारिक दस्तावेज यहां पाया जा सकता है

कार्यान्वयन

IdlingResource इंटरफ़ेस लागू करते समय आपको तीन चीजें करने की आवश्यकता IdlingResource है:

  • getName() - आपके निष्क्रिय संसाधन का नाम लौटाता है।
  • isIdleNow() - जाँचता है कि क्या आपका xyz ऑब्जेक्ट, ऑपरेशन, आदि इस समय निष्क्रिय है।
  • registerIdleTransitionCallback ( IdlingResource.ResourceCallback callback) - एक कॉलबैक प्रदान करता है जिसे आपको तब कॉल करना चाहिए जब आपका ऑब्जेक्ट निष्क्रिय हो जाए।

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

टिप्पणियाँ

  • Google के कुछ उदाहरण हैं जहां उन्होंने ऐप के कोड में IdlingResources डाला है। यह मत करो। उन्होंने संभवतः इसे सिर्फ यह दिखाने के लिए रखा कि वे कैसे काम करते हैं।
  • अपने कोड को साफ रखना और जिम्मेदारी के एकल सिद्धांत को बनाए रखना आपके ऊपर है!

उदाहरण

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

हमारे उदाहरण निष्क्रिय संसाधन को दो ऑब्जेक्ट मिलेंगे:

  • उस टुकड़े का टैग जो आपको गतिविधि से जुड़ने के लिए खोजने और प्रतीक्षा करने की आवश्यकता है।
  • एक FragmentManager वस्तु जिसका उपयोग टुकड़ा खोजने के लिए किया जाता है।
/**
 * FragmentIdlingResource - idling resource which waits while Fragment has not been loaded.
 */
public class FragmentIdlingResource implements IdlingResource {
    private final FragmentManager mFragmentManager;
    private final String mTag;
    //resource callback you use when your activity transitions to idle
    private volatile ResourceCallback resourceCallback;

    public FragmentIdlingResource(FragmentManager fragmentManager, String tag) {
        mFragmentManager = fragmentManager;
        mTag = tag;
    }

    @Override
    public String getName() {
        return FragmentIdlingResource.class.getName() + ":" + mTag;
    }

    @Override
    public boolean isIdleNow() {
        //simple check, if your fragment is added, then your app has became idle
        boolean idle = (mFragmentManager.findFragmentByTag(mTag) != null);
        if (idle) {
            //IMPORTANT: make sure you call onTransitionToIdle
            resourceCallback.onTransitionToIdle();
        }
        return idle;
    }

    @Override
    public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
        this.resourceCallback = resourceCallback;
    }
}

अब जब आपके पास अपना IdlingResource लिखा है, तो आपको इसे कहीं सही उपयोग करने की आवश्यकता है?

प्रयोग

आइए हम पूरे टेस्ट क्लास सेटअप को छोड़ दें और केवल यह देखें कि एक टेस्ट केस कैसा दिखेगा:

@Test
public void testSomeFragmentText() {
    mActivityTestRule.launchActivity(null);
   
    //creating the idling resource
    IdlingResource fragmentLoadedIdlingResource = new FragmentIdlingResource(mActivityTestRule.getActivity().getSupportFragmentManager(), SomeFragmentText.TAG);
    //registering the idling resource so espresso waits for it
    Espresso.registerIdlingResources(idlingResource1);
    onView(withId(R.id.txtHelloWorld)).check(matches(withText(helloWorldText)));

    //lets cleanup after ourselves
    Espresso.unregisterIdlingResources(fragmentLoadedIdlingResource);
}

JUnit नियम के साथ संयोजन

यह कठिन नहीं है; आप JUnit परीक्षण नियम के रूप में निष्क्रिय संसाधन भी लागू कर सकते हैं। उदाहरण के लिए, हम कहें कि आपके पास कुछ SDK हैं जिनमें वोली शामिल है और आप चाहते हैं कि एस्प्रेसो इसके लिए प्रतीक्षा करें। प्रत्येक परीक्षण मामले से गुजरने या इसे सेटअप में लागू करने के बजाय, आप एक JUnit नियम बना सकते हैं और बस लिख सकते हैं:

@Rule
public final SDKIdlingRule mSdkIdlingRule = new SDKIdlingRule(SDKInstanceHolder.getInstance());

अब चूंकि यह एक उदाहरण है, इसलिए इसे स्वीकार न करें; यहाँ सभी कोड काल्पनिक है और केवल प्रदर्शन प्रयोजनों के लिए उपयोग किया जाता है:

public class SDKIdlingRule implements TestRule {
    //idling resource you wrote to check is volley idle or not
    private VolleyIdlingResource mVolleyIdlingResource;
    //request queue that you need from volley to give it to idling resource
    private RequestQueue mRequestQueue;

    //when using the rule extract the request queue from your SDK
    public SDKIdlingRule(SDKClass sdkClass) {
        mRequestQueue = getVolleyRequestQueue(sdkClass);
    }

    private RequestQueue getVolleyRequestQueue(SDKClass sdkClass) {
        return sdkClass.getVolleyRequestQueue();
    }

    @Override
    public Statement apply(final Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                //registering idling resource
                mVolleyIdlingResource = new VolleyIdlingResource(mRequestQueue);
                Espresso.registerIdlingResources(mVolleyIdlingResource);
                try {
                    base.evaluate();
                } finally {
                    if (mVolleyIdlingResource != null) {
                        //deregister the resource when test finishes
                        Espresso.unregisterIdlingResources(mVolleyIdlingResource);
                    }
                }
            }
        };
    }
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow