2016-02-03 6 views
15

मैं अपने एंड्रॉइड ऐप के लिए इंस्ट्रुमेंटेशन टेस्ट लिखने की कोशिश कर रहा हूं।एंड्रॉइड इंस्ट्रूमेंटेशन टेस्टिंग - यूआई थ्रेड मुद्दे

मैं कुछ अजीब थ्रेडिंग मुद्दों में भाग रहा हूं और मुझे कोई समाधान नहीं मिल रहा है।

मेरे मूल टेस्ट:

@RunWith(AndroidJUnit4.class) 
public class WorkOrderDetailsTest { 

    @Rule 
    public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class); 

    @Test 
    public void loadWorkOrder_displaysCorrectly() throws Exception { 
     final WorkOrderDetails activity = activityRule.getActivity(); 

     WorkOrder workOrder = new WorkOrder(); 
     activity.updateDetails(workOrder); 

     //Verify customer info is displayed 
     onView(withId(R.id.customer_name)) 
       .check(matches(withText("John Smith"))); 
    } 
} 

यह एक

android.view.ViewRootImpl $ CalledFromWrongThreadException में हुई: केवल मूल बात यह है कि एक दृश्य पदानुक्रम बनाया अपने विचार छू सकता है।

...

com.kwtree.kwtree.workorder.WorkOrderDetails.updateDetails (WorkOrderDetails.java:155)

केवल एक चीज updateDetails() विधि करता है कुछ setText() कॉल है।

थोड़ा शोध करने के बाद, यह अपने परीक्षण करने के लिए एक UiThreadTestRule और android.support.test.annotation.UiThreadTest एनोटेशन जोड़ने समस्या को ठीक होगा की तरह लग रहा था।

@UiThreadTest:

@RunWith(AndroidJUnit4.class) 
public class WorkOrderDetailsTest { 

    //Note: This is new 
    @Rule 
    public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); 

    @Rule 
    public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class); 

    @Test 
    @UiThreadTest //Note: This is new 
    public void loadWorkOrder_displaysCorrectly() throws Exception { 
     final WorkOrderDetails activity = activityRule.getActivity(); 

     WorkOrder workOrder = new WorkOrder(); 
     activity.updateDetails(workOrder); 

     //Verify customer info is displayed 
     onView(withId(R.id.customer_name)) 
       .check(matches(withText("John Smith"))); 
    } 
} 

java.lang.IllegalStateException: विधि मुख्य आवेदन धागे पर बुलाया नहीं जा सकता है (पर: मुख्य)

(नोट: सभी इस स्टैक ट्रेस में विधियां मेरे कोड नहीं हैं)

ऐसा लगता है मुझे मिश्रित परिणाम दे रहे हैं ... यदि इसे मूल धागे पर चलने की ज़रूरत है जो दृश्यों को बनाता है लेकिन मुख्य धागे पर नहीं चल सकता है, तो इसे किस धागे पर चलाना चाहिए?

मैं वास्तव में किसी भी मदद या सुझाव की सराहना करता हूं!

उत्तर

13

वे उपकरण परीक्षण अपने ऐप के अंदर चलाए जाते हैं। इसका भी अर्थ है, वे अपने अपने धागे में चलाते हैं।

आपको अपने उपकरण के बारे में सोचना चाहिए जैसा कि आप अपने वास्तविक ऐप के साथ स्थापित करते हैं, इसलिए आपकी संभावित इंटरैक्शन 'सीमित' होती है।

आप आवेदन के UIThread/मुख्य थ्रेड से सभी दृश्य तरीकों कॉल करने की आवश्यकता है, तो बुला आपके उपकरण धागे से activity.updateDetails(workOrder);नहीं आवेदन मुख्य थ्रेड है। यही कारण है कि अपवाद फेंक दिया गया है।

तुम बस कोड आप अपने मुख्य थ्रेड पर परीक्षण करने के लिए की तरह अगर आप

activity.runOnUiThread(new Runnable() { 
    public void run() { 
     activity.updateDetails(workOrder); 
    } 
} 

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

आप जो अवैध राज्य अपवाद प्राप्त कर रहे हैं वह नियम के साथ आपकी बातचीत के कारण होता है। documentation राज्य

ध्यान दें कि इस एनोटेशन मौजूद होने पर उपकरण विधियों का उपयोग नहीं किया जा सकता है।

यदि आप @Before में अपनी गतिविधि शुरू/प्राप्त करते हैं तो यह भी काम करना चाहिए।

+1

'runOnUiThread' दृष्टिकोण जब' getInstrumentation() waitForIdleSync() के साथ संयुक्त काम किया, '।। '@ पहले' दृष्टिकोण दुर्भाग्य से काम नहीं किया था। सहायता के लिए धन्यवाद! – Khalos

12

आप UiThreadTestRule.runOnUiThread(Runnable) की मदद से मुख्य यूआई धागे पर अपने परीक्षण के हिस्से चला सकते हैं:,

@Rule 
public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); 

@Test 
public void loadWorkOrder_displaysCorrectly() throws Exception { 
    final WorkOrderDetails activity = activityRule.getActivity(); 

    uiThreadTestRule.runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      WorkOrder workOrder = new WorkOrder(); 
      activity.updateDetails(workOrder); 
     } 
    }); 

    //Verify customer info is displayed 
    onView(withId(R.id.customer_name)) 
      .check(matches(withText("John Smith"))); 
} 

ज्यादातर मामलों में यह UiThreadTest साथ परीक्षा पद्धति टिप्पणी करने के लिए आसान है, हालांकि, यह अन्य त्रुटियों देनी पड़ सकती है जैसे java.lang.IllegalStateException: Method cannot be called on the main application thread (on: main)

ध्यान दें, वर्तमान JUnit सीमा के कारण, Before और After साथ एनोटेट तरीकों में भी यूआई थ्रेड पर निष्पादित किया जाएगा:

यूगोस्लाविय, यहाँ UiThreadTest के जावाडोक से एक उद्धरण है। यदि यह कोई समस्या है तो runOnUiThread (Runnable) का उपयोग करने पर विचार करें।

कृपया ध्यान दें UiThreadTest (पैकेज android.support.test.annotation) ऊपर उल्लेख किया है (UiThreadTest (पैकेज android.test)) से अलग है।

0

स्वीकृत उत्तर वर्णन करता है कि पूरी तरह से क्या हो रहा है।

एक अतिरिक्त के रूप में, अगर कोई उत्सुक है कि एस्प्रेसो के तरीकों से यूआई को कैसे छूता है उदा। perform(ViewActions ...) को ऐसा करने की आवश्यकता नहीं है, यह केवल इसलिए है क्योंकि वे बाद में इसे हमारे लिए कर रहे हैं।

private void runSynchronouslyOnUiThread(Runnable action) { 
    ... 
    mainThreadExecutor.execute(uiTask); 
    ... 
} 

mainThreadExecutor ही @MainThread साथ टिप्पणी की जाती है कि:

आप perform(ViewActions ...) आप पाएंगे का पालन करें यह कर (android.support.test.espresso.ViewInteraction में) के बाद समाप्त होता है।

दूसरे शब्दों में, एस्प्रेसो को स्वीकार किए गए उत्तर पर डेविड द्वारा वर्णित नियमों द्वारा भी खेलना होगा।

9

स्वीकृत उत्तर बहिष्कृत किया गया है। अब यह करने के लिए सही तरीका बस है:

@Test 
@UiThreadTest 
public void myTest() { 
    // ... 
} 
संबंधित मुद्दे