स्पंदन अनुप्रयोगों का परीक्षण। शुरुआत

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



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


विजेट परीक्षण


सामान्य जानकारी


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


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


परीक्षण वाली फाइलें आमतौर पर परियोजना के परीक्षण उपनिर्देशिका में स्थित होती हैं।
टेस्ट या तो आईडीई से या कमांड से कंसोल से चलाए जा सकते हैं:


$ flutter test 

इस स्थिति में, परीक्षण उपनिर्देशिका से * _test.dart मास्क के साथ सभी परीक्षण निष्पादित किए जाएंगे।
आप फ़ाइल नाम निर्दिष्ट करके एक अलग परीक्षण चला सकते हैं:


 $ flutter test test/phone_screen_test.dart 

परीक्षण testWidgets फ़ंक्शन द्वारा बनाया गया है, जो परीक्षक पैरामीटर के रूप में एक टूल प्राप्त करता है, जिसके साथ परीक्षण कोड परीक्षण के तहत विजेट के साथ बातचीत करता है:


 testWidgets(' ', (WidgetTester tester) async { //   }); 

तार्किक ब्लॉकों में परीक्षणों को संयोजित करने के लिए, परीक्षण फ़ंक्शन को समूह फ़ंक्शन के अंदर समूहों में जोड़ा जा सकता है:


 group('  ', (){ testWidgets(' ', (WidgetTester tester) async { //   }); testWidgets(' ', (WidgetTester tester) async { //   }); }); 

सेटअप और टियरडाउन फ़ंक्शंस आपको प्रत्येक टेस्ट के बाद कुछ कोड "पहले" और "बाद" निष्पादित करने की अनुमति देते हैं। तदनुसार, setUpAll और tearDownAll फ़ंक्शन आपको सभी परीक्षणों को "पहले" और "बाद" कोड चलाने की अनुमति देते हैं, और यदि इन कार्यों को समूह के अंदर बुलाया जाता है, तो उन्हें समूह के सभी परीक्षणों के निष्पादन से पहले "और बाद" कहा जाएगा:


 setUp(() { //    }); tearDown(() { //    }); 

विजेट खोज


नेस्टेड विजेट पर कुछ क्रिया करने के लिए, आपको इसे विजेट ट्री में ढूंढना होगा। ऐसा करने के लिए, एक वैश्विक खोज ऑब्जेक्ट है जो आपको विजेट खोजने की अनुमति देता है:


  • पाठ द्वारा पेड़ में - find.text , find.widgetWithText ;
  • कुंजी द्वारा - find.byKey ;
  • आइकन द्वारा - find.byIcon , find.widgetWithIcon ;
  • प्रकार से - find.byType ;
  • पेड़ में स्थिति के अनुसार - find.descendant and find.ancestor ;
  • एक फ़ंक्शन का उपयोग करना जो किसी सूची पर विजेट का विश्लेषण करता है - find.byWidgetPredicate

टेस्ट विजेट इंटरेक्शन


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


  • पंपवेट - एक परीक्षण विजेट बनाएं;
  • पंप - विजेट के राज्य संक्रमण को संसाधित करना शुरू कर देता है और इसके लिए निर्धारित समय सीमा के भीतर पूरा होने का इंतजार करता है (डिफ़ॉल्ट रूप से 100 एमएस);
  • pumpAndSettle - किसी दिए गए टाइमआउट (डिफ़ॉल्ट रूप से 100 एमएस) के दौरान राज्यों को बदलने के लिए एक चक्र में पंप को कॉल करता है, यह सभी एनिमेशन के पूरा होने का इंतजार है;
  • टैप - विजेट पर एक क्लिक भेजें;
  • longPress - लंबा प्रेस;
  • fling - स्वाइप / स्वाइप;
  • खींचें - हस्तांतरण;
  • enterText - टेक्स्ट इनपुट।

परीक्षण सकारात्मक परिदृश्यों को लागू कर सकते हैं, नियोजित अवसरों की जाँच कर सकते हैं, और नकारात्मक यह सुनिश्चित करने के लिए कि वे घातक परिणामों की ओर नहीं ले जाते हैं, उदाहरण के लिए, जब कोई उपयोगकर्ता गलत दिशा में क्लिक करता है और आवश्यक नहीं होता है:


 await tester.enterText(find.byKey(Key('phoneField')), 'bla-bla-bla'); 

विगेट्स के साथ किसी भी कार्रवाई के बाद, आपको राज्यों को बदलने के लिए tester.pumpAndSettle () कॉल करने की आवश्यकता है।


Moki


कई मॉकिटो लाइब्रेरी से परिचित हैं। जावा दुनिया की यह लाइब्रेरी इतनी सफल रही कि डार्ट सहित कई प्रोग्रामिंग भाषाओं में इस लाइब्रेरी के कार्यान्वयन हैं।


कनेक्ट करने के लिए, आपको प्रोजेक्ट में निर्भरता को जोड़ना होगा। निम्नलिखित पंक्तियों को pubspec.yaml फ़ाइल में जोड़ें:


 dependencies: mockito: any 

और परीक्षण फ़ाइल में कनेक्ट करें:


 import 'package:mockito/mockito.dart'; 

यह लाइब्रेरी आपको मूक कक्षाएं बनाने की अनुमति देती है, जिस पर परीक्षण किया गया विजेट निर्भर करता है, ताकि परीक्षण सरल हो और केवल उस कोड को कवर करे जिसे हम परीक्षण कर रहे हैं।
उदाहरण के लिए, यदि हम PhoneInputScreen विजेट का परीक्षण करते हैं, जिस पर क्लिक करने पर, AuthInteractor सेवा का उपयोग करके ,Interactactor.checkAccess () बैकएंड का अनुरोध करता है, तो सेवा के बजाय मॉक को प्रतिस्थापित करते हुए, हम सबसे महत्वपूर्ण बात की जाँच कर सकते हैं - इस सेवा तक पहुँचने के तथ्य।


डिपेंडेंसी मॉब को मॉक क्लास के वंशज के रूप में बनाया जाता है और डिपेंडेंसी इंटरफेस को लागू किया जाता है:


 class AuthInteractorMock extends Mock implements AuthInteractor {} 

डार्ट में एक वर्ग भी एक इंटरफ़ेस है, इसलिए कुछ अन्य प्रोग्रामिंग भाषाओं की तरह, इंटरफ़ेस को अलग से घोषित करने की आवश्यकता नहीं है।


मोक की कार्यक्षमता का निर्धारण करने के लिए, जब फ़ंक्शन का उपयोग किया जाता है, जो आपको किसी विशेष फ़ंक्शन के लिए मॉक की प्रतिक्रिया निर्धारित करने की अनुमति देता है:


 when( authInteractor.checkAccess(any), ).thenAnswer((_) => Future.value(true)); 

Moki त्रुटियों या गलत डेटा वापस कर सकते हैं:


 when( authInteractor.checkAccess(any), ).thenAnswer((_) => Future.error(UnknownHttpStatusCode(null))); 

चेकों


परीक्षण के दौरान, आप स्क्रीन पर विजेट्स की जांच कर सकते हैं। यह आपको यह सुनिश्चित करने की अनुमति देता है कि वांछित विजेट्स की दृश्यता के मामले में स्क्रीन की नई स्थिति सही है:


 expect(find.text(' '), findsOneWidget); expect(find.text('  '), findsNothing); 

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


 verify(appComponent.authInteractor).called(1); verify(authInteractor.checkAccess(any)).called(1); verifyNever(appComponent.profileInteractor); 

डिबगिंग


बिना किसी ग्राफिक्स के कंसोल में टेस्ट किए जाते हैं। आप डिबग मोड में परीक्षण चला सकते हैं और विजेट कोड में ब्रेकपॉइंट सेट कर सकते हैं।


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


यह समझने के लिए कि विजेट मोकी का उपयोग कैसे करता है एक लॉगइनवोकेशंस () फ़ंक्शन है। यह एक पैरामीटर के रूप में मोक्सस की सूची लेता है और कंसोल को इन कॉलॉक्स के लिए विधि कॉल का एक क्रम जारी करता है जो परीक्षण में किए गए थे।


इस तरह के निष्कर्ष का एक उदाहरण नीचे है। वेरिफाइड मार्क उन कॉल्स पर होता है, जिन्हें वेरिफिकेशन फंक्शन का इस्तेमाल करके टेस्ट में चेक किया गया था:


 AppComponentMock.sessionChangedInteractor [VERIFIED] AppComponentMock.authInteractor [VERIFIED] AuthInteractorMock.checkAccess(71111111111) 

ट्रेनिंग


सभी आश्रितों को मोक के रूप में परीक्षण किए गए विजेट के लिए प्रस्तुत किया जाना चाहिए:


 class SomeComponentMock extends Mock implements SomeComponent {} class AuthInteractorMock extends Mock implements AuthInteractor {} 

परीक्षण किए गए घटक पर निर्भरता के हस्तांतरण को आपके आवेदन में स्वीकार किए गए तरीके से किया जाना चाहिए। कहानी कहने की सरलता के लिए, एक उदाहरण पर विचार करें जहां निर्भरता को कंस्ट्रक्टर के माध्यम से पारित किया जाता है।


कोड उदाहरण में, PhoneInputScreen स्कैफोल्ड में लिपटे StatefulWidget पर आधारित एक परीक्षण विजेट है। यह पंपवेट () फ़ंक्शन का उपयोग करके एक परीक्षण वातावरण में बनाया गया है:


 await tester.pumpWidget(PhoneInputScreen(mock)); 

हालाँकि, एक वास्तविक विजेट नेस्टेड विजेट्स के लिए अलाइनमेंट का उपयोग कर सकता है, जिसके लिए विजेट ट्री में MediaQuery की आवश्यकता होती है, इसे संभवतः नेविगेशन के लिए नेविगेटर (संदर्भ) प्राप्त होता है, इसलिए मटेरियलएप या क्यूपर्टिनोऐप में परीक्षण के तहत विजेट को लपेटना अधिक व्यावहारिक है:


 await tester.pumpWidget( MaterialApp( home: PhoneInputScreen(mock), ), ); 

एक परीक्षण विजेट बनाने और उसके साथ किसी भी क्रिया के बाद, आपको tester.pumpAndSettle () कॉल करने की आवश्यकता है ताकि परीक्षण वातावरण विजेट की स्थिति में सभी परिवर्तनों को संभाल सके।


एकीकरण परीक्षण


सामान्य जानकारी


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


एकीकरण परीक्षण आमतौर पर एक असली डिवाइस या एमुलेटर पर किया जाता है, जैसे कि आईओएस सिम्युलेटर या एंड्रॉइड एमुलेटर।


एकीकरण परीक्षण वाली फाइलें आमतौर पर परियोजना के test_driver उपनिर्देशिका में स्थित होती हैं।


एप्लिकेशन को परीक्षण ड्राइवर कोड से अलग किया जाता है और इसके बाद शुरू होता है। परीक्षण ड्राइवर आपको परीक्षण के दौरान एप्लिकेशन को नियंत्रित करने की अनुमति देता है। यह इस तरह दिखता है:


 import 'package:flutter_driver/driver_extension.dart'; import 'package:app_package_name/main.dart' as app; void main() { enableFlutterDriverExtension(); app.main(); } 

परीक्षण कमांड लाइन से चलाए जाते हैं। यदि एप्लिकेशन एप्लिकेशन के लॉन्च को app.dart फ़ाइल में वर्णित किया गया है, और परीक्षण स्क्रिप्ट को app_test.dart कहा जाता है, तो निम्न कमांड पर्याप्त है:


 $ flutter drive --target=test_driver/app.dart 

यदि परीक्षण स्क्रिप्ट का एक अलग नाम है, तो आपको इसे स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता है:


 $ flutter drive --target=test_driver/app.dart --driver=test_driver/home_test.dart 

परीक्षण फ़ंक्शन द्वारा एक परीक्षण बनाया जाता है, और समूह फ़ंक्शन द्वारा समूहीकृत किया जाता है।


 group('park-flutter app', () { // ,       FlutterDriver driver; //     setUpAll(() async { driver = await FlutterDriver.connect(); }); //     tearDownAll(() async { if (driver != null) { driver.close(); } }); test(' ', () async { //   }); test(' ', () async { //   }); } 

यह उदाहरण एक परीक्षण ड्राइवर बनाने के लिए कोड दिखाता है जिसके माध्यम से परीक्षण परीक्षण के तहत आवेदन के साथ बातचीत करते हैं।


परीक्षण किए गए आवेदन के साथ सहभागिता


FlutterDriver उपकरण परीक्षण विधि के साथ निम्नलिखित विधियों के माध्यम से बातचीत करता है:


  • टैप - विजेट पर एक क्लिक भेजें;
  • WaitFor - स्क्रीन पर विजेट के आने की प्रतीक्षा करें;
  • waForAbsent - विजेट के गायब होने की प्रतीक्षा करें;
  • स्क्रॉल करें और स्क्रॉल करें IntoView , ScrollUntilVigure - निर्दिष्ट ऑफसेट या इच्छित विजेट के लिए स्क्रीन स्क्रॉल करें;
  • enterText , getText - टेक्स्ट दर्ज करें या विजेट का टेक्स्ट लें;
  • स्क्रीनशॉट - एक स्क्रीनशॉट प्राप्त करें;
  • requestData - परीक्षण के तहत आवेदन के अंदर एक फ़ंक्शन कॉल के माध्यम से अधिक जटिल बातचीत।

ऐसी स्थिति हो सकती है जब आपको परीक्षण कोड से आवेदन की वैश्विक स्थिति को प्रभावित करने की आवश्यकता होती है। उदाहरण के लिए, मोकी के साथ आवेदन के भीतर सेवाओं का हिस्सा बदलकर एकीकरण परीक्षण को सरल बनाना। आवेदन में, आप एक अनुरोध हैंडलर निर्दिष्ट कर सकते हैं, जिसे परीक्षण कोड में Driver.requestData ('कुछ परम') पर कॉल के माध्यम से पहुँचा जा सकता है:


 void main() { Future<String> dataHandler(String msg) async { if (msg == "some param") { //       return 'some result'; } } enableFlutterDriverExtension(handler: dataHandler); app.main(); } 

विजेट खोज


वैश्विक खोज ऑब्जेक्ट के साथ एकीकरण परीक्षण के दौरान विजेट्स की खोज परीक्षण विजेट्स में समान कार्यक्षमता से विधियों की संरचना में भिन्न होती है। हालांकि, सामान्य अर्थ व्यावहारिक रूप से नहीं बदलता है:


  • पाठ द्वारा पेड़ में - find.text , find.widgetWithText ;
  • कुंजी द्वारा - find.byValueKey ;
  • प्रकार से - find.byType ;
  • प्रॉम्प्ट पर - find.byTooltip ;
  • सिमेंटिक लेबल द्वारा - find.bySemanticsLabel ;
  • पेड़ में स्थिति के अनुसार find.descendant और find.ancestor

निष्कर्ष


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


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

Source: https://habr.com/ru/post/hi468631/


All Articles