เช่น นักพัฒนาแอปที่มีประสบการณ์ ในขณะที่แอปพลิเคชันที่เราพัฒนาเติบโตเต็มที่เรารู้สึกได้ว่าถึงเวลาเริ่มการทดสอบแล้ว กฎทางธุรกิจมักจะบอกเป็นนัยว่าระบบต้องมีความเสถียรตลอดการเผยแพร่ที่แตกต่างกัน นอกจากนี้เรายังต้องการทำให้กระบวนการสร้างเป็นไปโดยอัตโนมัติและเผยแพร่แอปพลิเคชันโดยอัตโนมัติ สำหรับสิ่งนี้เราจำเป็นต้องมีเครื่องมือทดสอบ Adnroid เพื่อรับประกันว่าบิวด์ทำงานได้ตามที่คาดไว้
การทดสอบสามารถเพิ่มระดับความมั่นใจในสิ่งต่างๆที่เราสร้างขึ้น เป็นเรื่องยาก (ถ้าไม่เป็นไปไม่ได้) ที่จะสร้างผลิตภัณฑ์ที่สมบูรณ์แบบและปราศจากข้อบกพร่อง ดังนั้นเป้าหมายของเราคือการปรับปรุงโอกาสในการประสบความสำเร็จในตลาดโดยการตั้งค่าชุดทดสอบที่จะตรวจหาจุดบกพร่องที่เพิ่งเปิดตัวในแอปพลิเคชันของเราได้อย่างรวดเร็ว
เมื่อพูดถึง Android และแพลตฟอร์มมือถือต่างๆโดยทั่วไปการทดสอบแอปอาจเป็นเรื่องท้าทาย การใช้การทดสอบหน่วยและการปฏิบัติตามหลักการของการพัฒนาที่ขับเคลื่อนด้วยการทดสอบหรือการทดสอบที่คล้ายกันมักจะรู้สึกไม่เข้าใจ อย่างไรก็ตามการทดสอบมีความสำคัญและไม่ควรมองข้ามหรือเพิกเฉย เดวิด , เคนท์ และ มาร์ติน ได้กล่าวถึงประโยชน์และข้อผิดพลาดของการทดสอบในชุดการสนทนาระหว่างกันซึ่งรวบรวมไว้ในบทความชื่อ“ TDD ตายหรือไม่? ”. นอกจากนี้คุณยังสามารถค้นหาการสนทนาผ่านวิดีโอจริงได้ที่นั่นและรับข้อมูลเชิงลึกเพิ่มเติมว่าการทดสอบเหมาะกับขั้นตอนการพัฒนาของคุณหรือไม่และคุณจะรวมเข้าไว้ในขอบเขตใดได้ตั้งแต่ตอนนี้
ในบทช่วยสอนการทดสอบ Android นี้ฉันจะแนะนำคุณเกี่ยวกับหน่วยและการยอมรับการทดสอบการถดถอยบน Android เราจะมุ่งเน้นไปที่ส่วนที่เป็นนามธรรมของหน่วยการทดสอบบน Android ตามด้วยตัวอย่างการทดสอบการยอมรับโดยมุ่งเน้นที่การทำให้กระบวนการนี้รวดเร็วและง่ายที่สุดเท่าที่จะเป็นไปได้เพื่อลดวงจรการตอบรับ QA สำหรับนักพัฒนาซอฟต์แวร์
ความแตกต่างของ บริษัท c คอร์ปอเรชั่น
บทช่วยสอนนี้จะสำรวจความเป็นไปได้ต่างๆในการทดสอบแอปพลิเคชัน Android นักพัฒนาหรือผู้จัดการโครงการที่ต้องการทำความเข้าใจความเป็นไปได้ในการทดสอบปัจจุบันของแพลตฟอร์ม Android ให้ดีขึ้นสามารถตัดสินใจโดยใช้บทช่วยสอนนี้หากต้องการใช้แนวทางใด ๆ ที่กล่าวถึงในบทความนี้ อย่างไรก็ตามนี่ไม่ใช่สัญลักษณ์แสดงหัวข้อย่อยเงินเนื่องจากการสนทนาที่เกี่ยวข้องกับหัวข้อดังกล่าวโดยธรรมชาติแล้วจะแตกต่างกันไปในแต่ละผลิตภัณฑ์พร้อมกับกำหนดเวลาคุณภาพของโค้ดโค้ดระดับการเชื่อมต่อของระบบความชอบของผู้พัฒนาในการออกแบบสถาปัตยกรรมอายุการใช้งานที่คาดการณ์ไว้ของคุณลักษณะ ทดสอบ ฯลฯ
ตามหลักการแล้วเราต้องการทดสอบหน่วยตรรกะ / องค์ประกอบหนึ่งของสถาปัตยกรรมโดยอิสระ ด้วยวิธีนี้เราสามารถรับประกันได้ว่าส่วนประกอบของเราทำงานได้อย่างถูกต้องสำหรับชุดอินพุตที่เราคาดหวัง การอ้างอิงสามารถจำลองได้ซึ่งจะช่วยให้เราสามารถเขียนการทดสอบที่ดำเนินการได้อย่างรวดเร็ว นอกจากนี้เราจะสามารถจำลองสถานะของระบบต่างๆตามข้อมูลที่ป้อนให้กับการทดสอบซึ่งครอบคลุมกรณีที่แปลกใหม่ในกระบวนการ
เป้าหมายของ Android การทดสอบหน่วย คือการแยกแต่ละส่วนของโปรแกรมและแสดงว่าแต่ละส่วนถูกต้อง การทดสอบหน่วยให้สัญญาที่เข้มงวดและเป็นลายลักษณ์อักษรซึ่งชิ้นส่วนของรหัสต้องเป็นไปตามข้อกำหนด เป็นผลให้มีประโยชน์หลายประการ - วิกิพีเดีย
โรโบอิเล็กทริก เป็นกรอบการทดสอบหน่วย Android ที่ช่วยให้คุณสามารถเรียกใช้การทดสอบภายใน JVM บนเวิร์กสเตชันการพัฒนาของคุณ Robolectric จะเขียนคลาส Android SDK ใหม่ในขณะที่กำลังโหลดและทำให้สามารถรันบน JVM ปกติได้ทำให้เวลาทดสอบรวดเร็ว นอกจากนี้ยังจัดการกับอัตราการดูที่เพิ่มขึ้นการโหลดทรัพยากรและสิ่งอื่น ๆ ที่ติดตั้งในโค้ด C ดั้งเดิมบนอุปกรณ์ Android ทำให้จำเป็นต้องใช้ตัวเลียนแบบและอุปกรณ์ทางกายภาพเพื่อเรียกใช้การทดสอบอัตโนมัติที่ล้าสมัย
Mockito เป็นกรอบการเยาะเย้ยที่ช่วยให้เราสามารถเขียนการทดสอบทั้งหมดใน java ช่วยลดความยุ่งยากในกระบวนการสร้างคู่ทดสอบ (mocks) ซึ่งใช้เพื่อแทนที่การอ้างอิงเดิมของส่วนประกอบ / โมดูลที่ใช้ในการผลิต คำตอบ StackOverflow กล่าวถึง เกี่ยวกับความแตกต่างระหว่างล้อเลียนและต้นขั้ว ในรูปแบบที่ค่อนข้างง่ายที่คุณสามารถอ่านเพื่อเรียนรู้เพิ่มเติม
// you can mock concrete classes, not only interfaces LinkedList mockedList = mock(LinkedList.class); // stubbing appears before the actual execution when(mockedList.get(0)).thenReturn('first'); // the following prints 'first' System.out.println(mockedList.get(0)); // the following prints 'null' because get(999) was not stubbed System.out.println(mockedList.get(999));
นอกจากนี้ด้วย Mockito เราสามารถตรวจสอบได้ว่ามีการเรียกเมธอดหรือไม่:
// mock creation List mockedList = mock(List.class); // using mock object - it does not throw any 'unexpected interaction' exception mockedList.add('one'); mockedList.clear(); // selective, explicit, highly readable verification verify(mockedList).add('one'); verify(mockedList).clear();
ตอนนี้เรารู้แล้วว่าเราสามารถระบุคู่ปฏิกิริยาการกระทำที่กำหนดสิ่งที่จะเกิดขึ้นเมื่อเราดำเนินการเฉพาะกับวัตถุ / ส่วนประกอบที่ถูกจำลอง ดังนั้นเราสามารถจำลองโมดูลทั้งหมดของแอปพลิเคชันของเราและสำหรับแต่ละกรณีการทดสอบทำให้โมดูลที่จำลองนั้นตอบสนองในลักษณะที่แตกต่างกัน วิธีต่างๆจะสะท้อนถึงสถานะที่เป็นไปได้ของส่วนประกอบที่ทดสอบและคู่ของส่วนประกอบที่เยาะเย้ย
ในส่วนนี้เราจะใช้สถาปัตยกรรม MVP (Model View Presenter) กิจกรรมและส่วนย่อยคือมุมมองแบบจำลองซึ่งเป็นเลเยอร์พื้นที่เก็บข้อมูลสำหรับการเรียกไปยังฐานข้อมูลหรือบริการระยะไกลและผู้นำเสนอคือ 'สมอง' ที่เชื่อมโยงสิ่งเหล่านี้เข้าด้วยกันโดยใช้ตรรกะเฉพาะเพื่อควบคุมมุมมองแบบจำลองและการไหลของข้อมูลผ่าน ใบสมัคร
ในตัวอย่างการทดสอบ Android นี้เราจะล้อเลียนมุมมองโมเดลและส่วนประกอบที่เก็บและเราจะทดสอบผู้นำเสนอในหน่วย นี่คือหนึ่งในการทดสอบที่เล็กที่สุดโดยกำหนดเป้าหมายไปที่องค์ประกอบเดียวในสถาปัตยกรรม นอกจากนี้เราจะใช้วิธีการขีดฆ่าเพื่อสร้างห่วงโซ่ปฏิกิริยาที่เหมาะสมและทดสอบได้:
@RunWith(RobolectricTestRunner.class) @Config(manifest = 'app/src/main/AndroidManifest.xml', emulateSdk = 18) public class FitnessListPresenterTest { private Calendar cal = Calendar.getInstance(); @Mock private IFitnessListModel model; @Mock private IFitnessListView view; private IFitnessListPresenter presenter; @Before public void setup() { MockitoAnnotations.initMocks(this); final FitnessEntry entryMock = mock(FitnessEntry.class); presenter = new FitnessListPresenter(view, model); /* Define the desired behaviour. Queuing the action in 'doAnswer' for 'when' is executed. Clear and synchronous way of setting reactions for actions (stubbing). */ doAnswer((new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { ArrayList items = new ArrayList(); items.add(entryMock); ((IFitnessListPresenterCallback) presenter).onFetchAllSuccess(items); return null; } })).when(model).fetchAllItems((IFitnessListPresenterCallback) presenter); } /** Verify if model.fetchItems was called once. Verify if view.onFetchSuccess is called once with the specified list of type FitnessEntry The concrete implementation of ((IFitnessListPresenterCallback) presenter).onFetchAllSuccess(items); calls the view.onFetchSuccess(...) method. This is why we verify that view.onFetchSuccess is called once. */ @Test public void testFetchAll() { presenter.fetchAllItems(false); // verify can be called only on mock objects verify(model, times(1)).fetchAllItems((IFitnessListPresenterCallback) presenter); verify(view, times(1)).onFetchSuccess(new ArrayList(anyListOf(FitnessEntry.class))); } }
มักจะสะดวกในการจำลองเลเยอร์เครือข่ายทั่วโลก MockWebServer ช่วยให้เราสามารถจัดคิวการตอบกลับสำหรับคำขอเฉพาะที่เราดำเนินการในการทดสอบของเรา สิ่งนี้ทำให้เรามีโอกาสจำลองการตอบสนองที่คลุมเครือซึ่งเราคาดหวังจากเซิร์ฟเวอร์ แต่ไม่ตรงไปตรงมาในการสร้างซ้ำ ช่วยให้เรามั่นใจได้ว่าครอบคลุมทั้งหมดในขณะที่เขียนโค้ดเพิ่มเติมเล็กน้อย
ที่เก็บโค้ดของ MockWebServer เป็นตัวอย่างที่เป็นระเบียบซึ่งคุณสามารถอ้างถึงเพื่อความเข้าใจที่ดีขึ้นเกี่ยวกับไลบรารีนี้
คุณสามารถเขียนแบบจำลองหรือส่วนประกอบการหายใจของคุณเองและฉีดเข้าไปในการทดสอบโดยจัดเตรียมโมดูลอื่นให้กับกราฟวัตถุโดยใช้ Dagger (http://square.github.io/dagger/) เรามีตัวเลือกในการตรวจสอบว่าสถานะมุมมองได้รับการอัปเดตอย่างถูกต้องหรือไม่ตามข้อมูลที่จัดทำโดยส่วนประกอบโมเดลจำลอง:
/** Custom mock model class */ public class FitnessListErrorTestModel extends FitnessListModel { // ... @Override public void fetchAllItems(IFitnessListPresenterCallback callback) { callback.onError(); } @Override public void fetchItemsInRange(final IFitnessListPresenterCallback callback, DateFilter filter) { callback.onError(); } }
@RunWith(RobolectricTestRunner.class) @Config(manifest = 'app/src/main/AndroidManifest.xml', emulateSdk = 18) public class FitnessListPresenterDaggerTest { private FitnessActivity activity; private FitnessListFragment fitnessListFragment; @Before public void setup() { /* setupActivity runs the Activity lifecycle methods on the specified class */ activity = Robolectric.setupActivity(FitnessActivity.class); fitnessListFragment = activity.getFitnessListFragment(); /* Create the objectGraph with the TestModule */ ObjectGraph localGraph = ObjectGraph.create(TestModule.newInstance(fitnessListFragment)); /* Injection */ localGraph.inject(fitnessListFragment); localGraph.inject(fitnessListFragment.getPresenter()); } @Test public void testInteractorError() { fitnessListFragment.getPresenter().fetchAllItems(false); /* suppose that our view shows a Toast message with the specified text below when an error is reported, so we check for it. */ assertEquals(ShadowToast.getTextOfLatestToast(), 'Something went wrong!'); } @Module( injects = { FitnessListFragment.class, FitnessListPresenter.class }, overrides = true, library = true ) static class TestModule { private IFitnessListView view; private TestModule(IFitnessListView view){ this.view = view; } public static TestModule newInstance(IFitnessListView view){ return new TestModule(view); } @Provides public IFitnessListInteractor provideFitnessListInteractor(){ return new FitnessListErrorTestModel(); } @Provides public IFitnessListPresenter provideFitnessPresenter(){ return new FitnessListPresenter(view); } } }
คุณสามารถคลิกขวาที่คลาสทดสอบวิธีการหรือแพ็คเกจการทดสอบทั้งหมดและเรียกใช้การทดสอบจากกล่องโต้ตอบตัวเลือกใน IDE
iot และเทคโนโลยีสมาร์ทโฮม
การเรียกใช้การทดสอบแอป Android จากเทอร์มินัลจะสร้างรายงานสำหรับคลาสที่ทดสอบในโฟลเดอร์ 'build' ของโมดูลเป้าหมาย ยิ่งไปกว่านั้นหากคุณวางแผนที่จะตั้งค่ากระบวนการสร้างอัตโนมัติคุณจะใช้วิธีการเทอร์มินัล ด้วย Gradle คุณสามารถเรียกใช้การทดสอบรสชาติดีบักทั้งหมดโดยดำเนินการดังต่อไปนี้:
gradle testDebug
Android Studio เวอร์ชัน 1.1 และปลั๊กอิน Android Gradle รองรับหน่วยทดสอบโค้ดของคุณ คุณสามารถเรียนรู้เพิ่มเติมได้โดยอ่าน เอกสารที่ดีเยี่ยม . คุณลักษณะนี้อยู่ในระหว่างการทดลอง แต่ยังรวมไว้เป็นอย่างดีเนื่องจากตอนนี้คุณสามารถสลับระหว่างการทดสอบหน่วยและชุดแหล่งทดสอบเครื่องมือวัดจาก IDE ได้อย่างง่ายดาย มันทำงานในลักษณะเดียวกับที่คุณจะเปลี่ยนรสชาติใน IDE
การเขียนการทดสอบแอป Android อาจไม่สนุกเท่ากับการพัฒนาแอปพลิเคชันดั้งเดิม ดังนั้นเคล็ดลับบางประการเกี่ยวกับวิธีลดขั้นตอนการเขียนแบบทดสอบและหลีกเลี่ยงปัญหาที่พบบ่อยในขณะตั้งค่าโครงการจะช่วยได้นาน
AssertJ Android อย่างที่คุณอาจเดาได้จากชื่อคือชุดของฟังก์ชันตัวช่วยที่สร้างขึ้นโดยคำนึงถึง Android มันเป็นส่วนเสริมของห้องสมุดยอดนิยม AssertJ . ฟังก์ชันการทำงานของ AssertJ Android มีตั้งแต่การยืนยันอย่างง่ายเช่น“ assertThat (view) .isGone ()” ไปจนถึงสิ่งที่ซับซ้อนเช่น:
assertThat(layout).isVisible() .isVertical() .hasChildCount(4) .hasShowDividers(SHOW_DIVIDERS_MIDDLE)
ด้วย AssertJ Android และความสามารถในการขยายคุณจะรับประกันได้ว่าเป็นจุดเริ่มต้นที่ง่ายและดีสำหรับการทดสอบการเขียนสำหรับแอปพลิเคชัน Android
ในขณะที่ใช้ Robolectric คุณอาจสังเกตเห็นว่าคุณต้องระบุตำแหน่งรายการและเวอร์ชัน SDK ถูกตั้งค่าเป็น 18 คุณสามารถทำได้โดยใส่คำอธิบายประกอบ 'Config'
การเขียนกรณีทดสอบในภาษาจาวา
@Config(manifest = 'app/src/main/AndroidManifest.xml', emulateSdk = 18)
การเรียกใช้การทดสอบที่ต้องใช้ Robolectric จากเทอร์มินัลสามารถนำเสนอความท้าทายใหม่ ๆ ตัวอย่างเช่นคุณอาจเห็นข้อยกเว้นเช่น“ ไม่ได้ตั้งค่าธีม” หากการทดสอบกำลังดำเนินการอย่างถูกต้องจาก IDE แต่ไม่ใช่จากเทอร์มินัลคุณอาจพยายามเรียกใช้จากเส้นทางในเทอร์มินัลซึ่งไม่สามารถแก้ไขเส้นทางรายการที่ระบุได้ ค่ากำหนดค่าแบบฮาร์ดโค้ดสำหรับเส้นทางรายการอาจไม่ชี้ไปยังตำแหน่งที่ถูกต้องจากจุดดำเนินการของคำสั่ง สิ่งนี้สามารถแก้ไขได้โดยใช้นักวิ่งที่กำหนดเอง:
public class RobolectricGradleTestRunner extends RobolectricTestRunner { public RobolectricGradleTestRunner(Class testClass) throws InitializationError { super(testClass); } @Override protected AndroidManifest getAppManifest(Config config) { String appRoot = '../app/src/main/'; String manifestPath = appRoot + 'AndroidManifest.xml'; String resDir = appRoot + 'res'; String assetsDir = appRoot + 'assets'; AndroidManifest manifest = createAppManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir)); return manifest; } }
คุณสามารถใช้สิ่งต่อไปนี้เพื่อกำหนดค่า Gradle สำหรับการทดสอบหน่วย คุณอาจต้องแก้ไขชื่ออ้างอิงและเวอร์ชันที่ต้องการตามความต้องการของโครงการ
// Robolectric testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.9.5' testCompile 'com.squareup.dagger:dagger:1.2.2' testProvided 'com.squareup.dagger:dagger-compiler:1.2.2' testCompile 'com.android.support:support-v4:21.0.+' testCompile 'com.android.support:appcompat-v7:21.0.3' testCompile('org.robolectric:robolectric:2.4') { exclude module: 'classworlds' exclude module: 'commons-logging' exclude module: 'httpclient' exclude module: 'maven-artifact' exclude module: 'maven-artifact-manager' exclude module: 'maven-error-diagnostics' exclude module: 'maven-model' exclude module: 'maven-project' exclude module: 'maven-settings' exclude module: 'plexus-container-default' exclude module: 'plexus-interpolation' exclude module: 'plexus-utils' exclude module: 'wagon-file' exclude module: 'wagon-http-lightweight' exclude module: 'wagon-provider-api' }
หากคุณใช้บริการ Google Play คุณจะต้องสร้างค่าคงที่จำนวนเต็มของคุณเองสำหรับเวอร์ชัน Play Services เพื่อให้ Robolectric ทำงานได้อย่างถูกต้องในการกำหนดค่าแอปพลิเคชันนี้
android.library.reference.1=../../build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3 android.library.reference.2=../../build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3
อีก น่าสนใจ ปัญหาในการทดสอบคือ Robolectric ไม่สามารถอ้างอิงไลบรารีสนับสนุนได้อย่างถูกต้อง วิธีแก้ปัญหาคือการเพิ่มไฟล์“ project.properties” ลงในโมดูลที่มีการทดสอบ ตัวอย่างเช่นสำหรับไลบรารี Support-v4 และ AppCompat ไฟล์ควรมี:
public class LoginTest extends ActivityInstrumentationTestCase2 { private static final String LAUNCHER_ACTIVITY_CLASSNAME = 'com.toptal.fitnesstracker.view.activity.SplashActivity'; private static Class launchActivityClass; static { try { launchActivityClass = Class.forName(LAUNCHER_ACTIVITY_CLASSNAME); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } private ExtSolo solo; @SuppressWarnings('unchecked') public LoginTest() { super((Class) launchActivityClass); } // executed before every test method @Override public void setUp() throws Exception { super.setUp(); solo = new ExtSolo(getInstrumentation(), getActivity(), this.getClass() .getCanonicalName(), getName()); } // executed after every test method @Override public void tearDown() throws Exception { solo.finishOpenedActivities(); solo.tearDown(); super.tearDown(); } public void testRecorded() throws Exception { try { assertTrue( 'Wait for edit text (id: com.toptal.fitnesstracker.R.id.login_username_input) failed.', solo.waitForEditTextById( 'com.toptal.fitnesstracker.R.id.login_username_input', 20000)); solo.enterText( (EditText) solo .findViewById('com.toptal.fitnesstracker.R.id.login_username_input'), ' [email protected] '); solo.sendKey(ExtSolo.ENTER); solo.sleep(500); assertTrue( 'Wait for edit text (id: com.toptal.fitnesstracker.R.id.login_password_input) failed.', solo.waitForEditTextById( 'com.toptal.fitnesstracker.R.id.login_password_input', 20000)); solo.enterText( (EditText) solo .findViewById('com.toptal.fitnesstracker.R.id.login_password_input'), '123456'); solo.sendKey(ExtSolo.ENTER); solo.sleep(500); assertTrue( 'Wait for button (id: com.toptal.fitnesstracker.R.id.parse_login_button) failed.', solo.waitForButtonById( 'com.toptal.fitnesstracker.R.id.parse_login_button', 20000)); solo.clickOnButton((Button) solo .findViewById('com.toptal.fitnesstracker.R.id.parse_login_button')); assertTrue('Wait for text fitness list activity.', solo.waitForActivity(FitnessActivity.class)); assertTrue('Wait for text KM.', solo.waitForText('KM', 20000)); /* Custom class that enables proper clicking of ActionBar action items */ TestUtils.customClickOnView(solo, R.id.action_logout); solo.waitForDialogToOpen(); solo.waitForText('OK'); solo.clickOnText('OK'); assertTrue('waiting for ParseLoginActivity after logout', solo.waitForActivity(ParseLoginActivity.class)); assertTrue( 'Wait for button (id: com.toptal.fitnesstracker.R.id.parse_login_button) failed.', solo.waitForButtonById( 'com.toptal.fitnesstracker.R.id.parse_login_button', 20000)); } catch (AssertionFailedError e) { solo.fail( 'com.example.android.apis.test.Test.testRecorded_scr_fail', e); throw e; } catch (Exception e) { solo.fail( 'com.example.android.apis.test.Test.testRecorded_scr_fail', e); throw e; } } }
การทดสอบการยอมรับ / การถดถอยเป็นส่วนหนึ่งของขั้นตอนสุดท้ายของการทดสอบโดยอัตโนมัติบนสภาพแวดล้อม Android จริง 100% เราไม่ใช้คลาส Android OS จำลองในระดับนี้ - การทดสอบจะทำงานบนอุปกรณ์จริงและอีมูเลเตอร์
สถานการณ์เหล่านี้ทำให้กระบวนการไม่เสถียรมากขึ้นเนื่องจากความหลากหลายของอุปกรณ์จริงการกำหนดค่าโปรแกรมจำลองสถานะอุปกรณ์และชุดคุณลักษณะของอุปกรณ์แต่ละเครื่อง นอกจากนี้ยังขึ้นอยู่กับเวอร์ชันของระบบปฏิบัติการและขนาดหน้าจอของโทรศัพท์ในการตัดสินใจว่าจะแสดงเนื้อหาอย่างไร
เป็นเรื่องที่ซับซ้อนเล็กน้อยในการสร้างการทดสอบที่เหมาะสมซึ่งส่งผ่านอุปกรณ์หลากหลายประเภท แต่คุณควรฝันที่ยิ่งใหญ่ แต่เริ่มจากเล็ก ๆ การสร้างการทดสอบด้วย Robotium เป็นกระบวนการซ้ำ ๆ ด้วยเทคนิคเล็ก ๆ น้อย ๆ ก็สามารถทำให้ง่ายขึ้นได้มาก
หุ่นยนต์ เป็นกรอบการทดสอบอัตโนมัติแบบโอเพ่นซอร์สของ Android ที่มีมาตั้งแต่เดือนมกราคม 2010 เป็นที่น่ากล่าวขวัญว่า Robotium เป็นโซลูชันแบบชำระเงิน แต่มาพร้อมกับการทดลองใช้ฟรีที่ยุติธรรม
เพื่อเร่งกระบวนการเขียนการทดสอบ Robotium เราจะย้ายออกจากการเขียนทดสอบด้วยตนเองเป็นการทดสอบการบันทึก การแลกเปลี่ยนระหว่างคุณภาพของรหัสและความเร็ว หากคุณทำการเปลี่ยนแปลงอย่างหนักในส่วนติดต่อผู้ใช้ของคุณคุณจะได้รับประโยชน์มากมายจากวิธีการบันทึกการทดสอบและสามารถบันทึกการทดสอบใหม่ได้อย่างรวดเร็ว
Testdroid Recorder เป็นเครื่องบันทึกการทดสอบฟรีที่สร้างการทดสอบ Robotium เนื่องจากบันทึกการคลิกที่คุณดำเนินการบนอินเทอร์เฟซผู้ใช้ การติดตั้งเครื่องมือนั้นง่ายมากเช่นกัน อธิบายไว้ในเอกสารของพวกเขา พร้อมกับวิดีโอทีละขั้นตอน
เนื่องจาก Testdroid Recorder เป็นปลั๊กอิน Eclipse และเราอ้างถึง Android Studio ตลอดบทความนี้จึงเป็นเหตุผลที่น่ากังวล อย่างไรก็ตามในกรณีนี้ไม่ใช่ปัญหาเนื่องจากคุณสามารถใช้ปลั๊กอินโดยตรงกับ APK และบันทึกการทดสอบกับมัน
เมื่อคุณสร้างการทดสอบคุณสามารถคัดลอกและวางใน Android Studio พร้อมกับการพึ่งพาใด ๆ ที่เครื่องบันทึก Testdroid ต้องการและคุณพร้อมที่จะไป การทดสอบที่บันทึกไว้จะมีลักษณะคล้ายกับชั้นเรียนด้านล่าง:
อาสนะ vs เทรลโล vs เบสแคมป์
gradle connectedAndroidTest
หากคุณมองอย่างใกล้ชิดคุณจะสังเกตเห็นว่าโค้ดค่อนข้างตรงไปตรงมามากแค่ไหน
เมื่อบันทึกการทดสอบอย่าไปหาคำสั่ง 'รอ' รอให้กล่องโต้ตอบปรากฏขึ้นกิจกรรมที่จะปรากฏข้อความจะปรากฏขึ้น สิ่งนี้จะรับประกันว่ากิจกรรมและลำดับชั้นมุมมองพร้อมที่จะโต้ตอบเมื่อคุณดำเนินการบนหน้าจอปัจจุบัน ในเวลาเดียวกันให้จับภาพหน้าจอ โดยปกติการทดสอบอัตโนมัติจะไม่มีใครดูแลและภาพหน้าจอเป็นวิธีหนึ่งที่คุณจะได้เห็นสิ่งที่เกิดขึ้นจริงระหว่างการทดสอบเหล่านั้น
ไม่ว่าการทดสอบจะผ่านหรือล้มเหลวรายงานคือเพื่อนที่ดีที่สุดของคุณ คุณสามารถค้นหาได้ภายใต้ไดเร็กทอรี build“ module / build / outputs / reports”:
ในทางทฤษฎีทีม QA สามารถบันทึกการทดสอบและเพิ่มประสิทธิภาพได้ การใช้ความพยายามในรูปแบบมาตรฐานสำหรับการเพิ่มประสิทธิภาพกรณีทดสอบนั้นสามารถทำได้ เมื่อคุณบันทึกการทดสอบตามปกติคุณจะต้องปรับแต่งสองสามอย่างเพื่อให้ทำงานได้อย่างไม่มีที่ติ
สุดท้ายในการเรียกใช้การทดสอบเหล่านี้จาก Android Studio คุณสามารถเลือกและเรียกใช้ตามที่เรียกใช้การทดสอบหน่วย จากเทอร์มินัลมันเป็นซับเดียว:
|_+_|
การทดสอบหน่วย Android ด้วย Robolectric นั้นเร็วมากเพราะมันทำงานโดยตรงภายใน JVM บนเครื่องของคุณ เมื่อเทียบกับสิ่งนั้นการทดสอบการยอมรับบนอีมูเลเตอร์และอุปกรณ์ทางกายภาพนั้นช้ากว่ามาก ขึ้นอยู่กับขนาดของโฟลว์ที่คุณกำลังทดสอบอาจใช้เวลาไม่กี่วินาทีถึงสองสามนาทีต่อกรณีทดสอบ ควรใช้ขั้นตอนการทดสอบการยอมรับเป็นส่วนหนึ่งของกระบวนการสร้างอัตโนมัติบนเซิร์ฟเวอร์การรวมแบบต่อเนื่อง
ความเร็วสามารถปรับปรุงได้โดยการขนานบนอุปกรณ์หลายเครื่อง ตรวจสอบเครื่องมือที่ยอดเยี่ยมนี้จาก เจควอร์ตัน และพวกที่ Square http://square.github.io/spoon/ . มีการรายงานที่ดีด้วย
มีเครื่องมือทดสอบ Android มากมายให้ใช้งานและเมื่อระบบนิเวศเติบโตเต็มที่กระบวนการตั้งค่าสภาพแวดล้อมที่ทดสอบได้และการทดสอบการเขียนจะง่ายขึ้น ยังคงมีความท้าทายอีกมากที่ต้องจัดการและด้วยชุมชนนักพัฒนาที่ทำงานกับปัญหาประจำวันจำนวนมากจึงมีพื้นที่มากมายสำหรับการอภิปรายที่สร้างสรรค์และการตอบรับที่รวดเร็ว
ใช้แนวทางที่อธิบายไว้ในบทช่วยสอนการทดสอบ Android นี้เพื่อเป็นแนวทางในการรับมือกับความท้าทายที่รอคุณอยู่ หากและเมื่อคุณประสบปัญหาโปรดกลับมาตรวจสอบบทความนี้หรือข้อมูลอ้างอิงที่เชื่อมโยงภายในเพื่อหาแนวทางแก้ไขปัญหาที่ทราบ
ในโพสต์ในอนาคตเราจะพูดถึงการทำงานแบบขนาน, การสร้างระบบอัตโนมัติ, การผสานรวมอย่างต่อเนื่อง, ตะขอ Github / BitBucket, การกำหนดเวอร์ชันสิ่งประดิษฐ์และแนวทางปฏิบัติที่ดีที่สุดสำหรับการจัดการโครงการแอปพลิเคชันมือถือขนาดใหญ่ในเชิงลึกมากขึ้น