Scaling Pengujian Android di Odnoklassniki



Halo! Nama saya Roman Ivanitsky, saya bekerja di tim otomatisasi pengujian Odnoklassniki. OK adalah layanan besar dengan lebih dari 70 juta pengguna. Jika kita berbicara tentang perangkat seluler, mayoritas menggunakan OK.RU di ponsel pintar yang menjalankan Android. Untuk alasan ini, kami sangat serius dalam menguji aplikasi Android kami. Pada artikel ini saya akan menceritakan tentang perkembangan pengujian otomatis di perusahaan kami.

2012, Odnoklassniki, perusahaan ini mengalami peningkatan aktif dalam jumlah pengguna dan peningkatan jumlah fitur pengguna. Untuk memenuhi tujuan bisnis, perlu untuk mempersingkat siklus rilis, tetapi ini terhambat oleh kenyataan bahwa semua fungsi diuji secara manual. Solusi untuk masalah ini datang dengan sendirinya - kita perlu autotest. Jadi, pada tahun 2012 di Odnoklassniki, tim otomasi uji muncul, dan langkah pertama adalah mulai menulis tes.

Sedikit sejarah


Autotest pertama di Odnoklassniki ditulis dalam Selenium, untuk peluncuran mereka mereka mengangkat Jenkins, Selenium Grid dengan Selenium Hub dan satu set Selenium Node.

Solusi cepat, mulai cepat, laba cepat - sempurna.

Seiring waktu, jumlah tes meningkat, dan layanan tambahan muncul - misalnya, layanan peluncuran, layanan laporan, layanan data uji. Pada akhir 2014, kami memiliki seribu tes yang berlangsung sekitar lima belas hingga dua puluh menit. Ini tidak cocok untuk kami, karena jelas bahwa jumlah tes akan meningkat, dan dengan itu waktu yang dibutuhkan untuk menjalankannya akan meningkat.

Pada saat itu, infrastruktur pengujian otomatis terlihat seperti ini:



Namun, dengan jumlah Selenium Node lebih besar dari atau sama dengan 200, Hub tidak dapat mengatasi beban. Sekarang masalah ini telah dipelajari, dan itulah sebabnya alat seperti Zalenium atau Selenoid favorit semua orang muncul. Tetapi pada 2014 tidak ada solusi standar, jadi kami memutuskan untuk membuat sendiri.

Menetapkan persyaratan minimum yang harus dipenuhi oleh layanan:

  1. Skalabilitas. Kami tidak ingin bergantung pada keterbatasan Selenium Hub.
  2. Stabilitas. Pada tahun 2014, Selenium Hub tidak terkenal dengan operasi yang stabil.
  3. Toleransi kesalahan. Kami membutuhkan kemampuan untuk melanjutkan proses pengujian jika terjadi kegagalan pusat data atau server mana pun.

Dengan demikian, solusi kami untuk penskalaan Selenium Grid muncul, yang terdiri dari koordinator dan Node-manajer, di luar sangat mirip dengan Selenium Grid standar, tetapi dengan fitur-fiturnya sendiri. Fitur-fitur ini akan dibahas lebih lanjut.

Koordinator




Bahkan, ini adalah broker sumber daya (sumber daya dipahami sebagai browser). Ini memiliki API eksternal di mana tes mengirim permintaan untuk sumber daya. Pertanyaan-pertanyaan ini disimpan ke database sebagai tugas untuk dijalankan. Koordinator tahu segalanya tentang konfigurasi cluster kami - yang ada di manajer Node, jenis sumber daya apa yang dapat disediakan oleh manajer Node ini, jumlah total sumber daya, berapa banyak sumber daya yang saat ini terlibat dalam tugas-tugas tersebut. Pada saat yang sama, ia memantau sumber daya - aktivitas, stabilitas, dan dalam hal ini memberi tahu mereka yang bertanggung jawab.

Fitur koordinator adalah bahwa ia mengintegrasikan semua manajer Node ke dalam pertanian yang disebut.

Seperti inilah bentuk pertanian itu. Lebih dari setengah sumber daya digunakan, dan semua node online:



Anda juga dapat menampilkan node offline atau memasukkannya ke dalam rotasi dengan persentase tertentu, ini diperlukan jika menjadi perlu untuk mengurangi beban pada node tertentu.

Setiap tambak dapat digabungkan dengan yang lain dalam unit logis, yang kami sebut layanan. Pada saat yang sama, satu tambak dapat dimasukkan dalam beberapa layanan berbeda. Pertama, memungkinkan untuk menetapkan batas dan memprioritaskan sumber daya yang digunakan oleh setiap layanan tertentu. Kedua, ini memungkinkan Anda untuk mengelola konfigurasi dengan mudah - kami memiliki kemampuan untuk menambahkan jumlah manajer Node dalam layanan dengan cepat, atau sebaliknya untuk menghapusnya dari tambak agar dapat berinteraksi dengan manajer Node ini, misalnya, mengkonfigurasi atau memperbarui, dll. .



API koordinator sangat sederhana: dimungkinkan untuk meminta layanan untuk jumlah sumber daya saat ini yang digunakan, dapatkan batasnya dan mulai atau hentikan beberapa sumber daya.

Manajer Node


Ini adalah layanan yang dapat melakukan dua hal dengan baik - menerima tugas dari koordinator dan meluncurkan beberapa sumber daya sesuai permintaan. Secara default, ini dirancang agar setiap peluncuran sumber daya diisolasi, yaitu, tidak ada peluncuran sebelumnya yang dapat mempengaruhi peluncuran pengujian berikutnya. Sebagai tanggapan, koordinator menggunakan sekelompok host dan satu set port yang ditinggikan. Misalnya, host tempat server Selenium diluncurkan, dan porta.



Pada host, sepertinya ini: layanan manajer Node sedang berjalan, dan mengelola seluruh siklus hidup sumber daya. Dia mengambil browser, menyelesaikannya, memastikan bahwa mereka tidak lupa untuk menutup. Untuk menjamin isolasi satu sama lain, semua ini terjadi atas nama pengguna layanan.

Interaksi


Tes berinteraksi dengan infrastruktur yang dijelaskan di atas sebagai berikut: ini membahas koordinator dengan permintaan untuk sumber daya yang diperlukan, koordinator menyimpan tugas ini sebagai membutuhkan eksekusi.

Manajer Node, pada gilirannya, beralih ke koordinator tugas. Setelah menerima tugas itu, ia memulai sumber dayanya. Setelah itu, ia mengirimkan hasil peluncuran ke koordinator, gagal memulai juga dilaporkan ke koordinator. Tes menerima hasil permintaan sumber daya dan, jika berhasil, mulai bekerja dengan sumber daya secara langsung.



Keuntungan dari pendekatan ini adalah untuk mengurangi beban pada koordinator dengan mendapatkan kemampuan untuk bekerja dengan sumber daya secara langsung. Kontra - kebutuhan untuk mengimplementasikan logika interaksi dengan koordinator dalam kerangka kerja pengujian, tetapi bagi kami ini dapat diterima.
Hari ini kita dapat menjalankan lebih dari 800 browser secara paralel di tiga pusat data. Untuk koordinator, ini bukan batasnya.

Toleransi kesalahan dijamin dengan peluncuran beberapa contoh koordinator di belakang firewall DNS di pusat data yang berbeda. Ini menjamin akses ke instance yang berfungsi jika terjadi masalah dengan pusat data atau server.

Sebagai hasilnya, kami mendapat solusi yang memenuhi semua persyaratan yang ditetapkan sebelumnya. Ini telah beroperasi terus sejak 2015 dan telah membuktikan efektivitasnya.

Android


Ketika datang ke pengujian di Android, biasanya ada dua pendekatan utama. Yang pertama adalah menggunakan WebDriver - ini adalah cara kerja Selendroid dan Appium. Yang kedua - dalam bekerja dengan alat asli, dengan demikian mengimplementasikan Robotium, UI Automator atau Espresso.

Kesamaan mendasar antara pendekatan ini adalah untuk mendapatkan perangkat dan mendapatkan browser.

Ada lebih banyak perbedaan, yang utama adalah kebutuhan untuk menginstal APK yang diuji, dengan mana kita akan mengambil artefak dalam bentuk log, screenshot, dll. dan juga, fakta bahwa pengujian dilakukan pada perangkat itu sendiri, dan bukan pada CI.

Pada 2015, Odnoklassniki mulai menutupi aplikasi Android mereka dengan autotest. Kami memilih satu mesin Linux, menghubungkan satu perangkat nyata melalui USB dan mulai menulis tes pada Robotium. Solusi sederhana ini memungkinkan Anda mendapatkan hasil dengan cepat.

Waktu berlalu, jumlah tes dan jumlah perangkat bertambah. Untuk menyelesaikan tugas manajemen, Device Manager telah dibuat - perintah wrapper over adb (Android Debug Bridge), yang memungkinkan antarmuka http api untuk menjalankannya.

Ini adalah bagaimana API pertama untuk Device Manager terlihat - dengan bantuannya Anda bisa mendapatkan daftar perangkat, menginstal / mencopot APK, menjalankan tes dan mendapatkan hasil.



Namun, kami memperhatikan bahwa hasil pengujian menurun saat startup di server ADB yang terhubung dengan lebih dari satu perangkat. Solusi yang membantu kami meningkatkan stabilitas ditemukan dalam mengisolasi setiap server ADB menggunakan Docker.

Peternakan sudah siap - Anda dapat menghubungkan ponsel.



Banyak yang akrab dengan gambar ini. Saya mendengar bahwa jika Anda terlibat dalam pertanian Android, Anda seolah-olah di neraka setiap hari.



Emulator Android datang membantu kami. Penggunaannya disebabkan oleh dua faktor: pertama, pada saat itu sudah mencapai tingkat stabilitas yang diperlukan, dan kedua, kami tidak memiliki fitur yang akan bergantung secara khusus pada setrika dalam pengujian kami. Selain itu, emulator ini diproyeksikan dengan baik ke infrastruktur yang ada pada saat itu. Langkah selanjutnya adalah mengajar manajer Node untuk meluncurkan sumber daya jenis baru.

Apa yang diperlukan untuk menjalankan emulator Android?

Pertama, Anda memerlukan Android SDK dengan satu set utilitas.

Maka Anda perlu membuat AVD - Perangkat Virtual Android - ini adalah bagaimana emulator Android Anda akan diatur - arsitektur apa yang akan dimilikinya, berapa inti yang akan digunakan, apakah layanan Google akan tersedia, dll.



Setelah itu, Anda perlu memilih nama AVD yang dibuat, mengatur parameter, misalnya, mentransfer port tempat ADB akan diluncurkan, dan mulai.

Namun, ada kekhasan dalam skema semacam itu - sistem ini memungkinkan Anda untuk hanya menjalankan satu emulator instance pada satu AVD tertentu.

Solusi untuk masalah ini adalah membuat AVD dasar, yang disimpan dalam memori, ini memungkinkan untuk menyalinnya di tempat lain. Selama peluncuran emulator Android, basis AVD disalin ke direktori sementara yang dipetakan ke dalam memori, setelah itu dimulai. Skema semacam itu bekerja dengan cepat, tetapi rumit. Sampai saat ini, masalah ini telah dipecahkan oleh opsi hanya baca, yang memungkinkan Anda untuk menjalankan emulator Android dalam jumlah tak terbatas dari satu AVD

Performa


Berdasarkan hasil bekerja dengan AVD, kami mengembangkan beberapa rekomendasi internal:

  1. 86 , ARM . dev/kvm Linux HAXM- Mac Windows
  2. GPU- . , . , , , Android-
  3. .
  4. , localhost,

Adapun gambar Docker untuk pengujian di Android, saya ingin menyoroti Agoda dan Selenoid, mereka menggunakan kemampuan emulator Android secara maksimal.

Perbedaan di antara mereka adalah bahwa dalam Selenoid default memiliki Appium , Agoda dan menggunakan emulator "bersih". Selain itu, Selenoid memiliki lebih banyak dukungan komunitas.

Pada akhir 2018, CloudNode-Manager telah dibuat, ia menghubungi koordinator, menerima tugas dan diluncurkan menggunakan perintah di cloud. Alih-alih mesin besi, layanan ini menggunakan sumber daya one-cloud - cloud pribadi Odnoklassniki sendiri.

Kami berhasil mencapai penskalaan dengan mengajarkan DeviceManager cara bekerja dengan Koordinator. Untuk melakukan ini, saya harus mengubah API Pengelola perangkat untuk menambahkan kemampuan untuk meminta jenis perangkat (virtual / nyata).

Inilah yang terjadi jika Anda mencoba menjalankan Instalasi ADB pada 250 emulator dari satu mesin.



Para petugas segera bereaksi terhadap hal ini dan memulai sebuah insiden - mesin memuat antarmuka jaringan gigabit dengan lalu lintas keluar. Kompleksitas ini diatasi dengan meningkatkan throughput di server. Saya tidak bisa mengatakan bahwa masalah ini memberi kami banyak masalah, tetapi Anda tidak boleh melupakannya.

Tampaknya kesuksesan adalah Devicemanager, koordinator, scaling. Kita dapat menjalankan tes di seluruh peternakan. Pada prinsipnya, kami dapat menjalankannya pada setiap permintaan tarik, dan pengembang akan segera menerima umpan balik.



Tapi tidak semuanya begitu cerah. Anda mungkin telah memperhatikan bahwa sejauh ini tidak ada yang dikatakan tentang kualitas tes.



Seperti inilah peluncuran kami. Dan hal yang paling menarik adalah bahwa antara peluncuran tes yang sama sekali berbeda bisa jatuh. Ini adalah air terjun yang tidak stabil. Dan saya, pengembang, atau penguji tidak mempercayai hasil ini.

Bagaimana kami menangani masalah ini? Mereka hanya menyalin semuanya dari Robotium ke Espresso, dan itu menjadi baik ... Sebenarnya, tidak.

Untuk mengatasi masalah ini, kami tidak hanya menulis ulang semua yang ada di Espresso, tetapi juga mulai menggunakan API untuk semua jenis tindakan seperti mengunggah foto, membuat posting, menambah teman, dll., Membuat login cepat, menggunakan diplink yang memungkinkan Anda untuk langsung pergi ke layar yang diinginkan , dan, tentu saja, kami menganalisis semua kasus uji.

Sekarang tes berjalan terlihat seperti ini:



Anda mungkin memperhatikan bahwa tes merah tetap ada, tetapi penting untuk diingat bahwa ini adalah tes end-to-end yang berjalan pada produksi. Kami memiliki batasan jumlah tes yang dapat jatuh di cabang utama aplikasi.

Sekarang kami memiliki tes dan penskalaan yang stabil. Namun, infrastruktur uji masih sangat terkait dengan tes. Pada saat yang sama, karena harapan dari tes end-to-end, CI sibuk, dan majelis lain dapat mengantri, menunggu agen bebas. Selain itu, tidak ada skema yang jelas untuk bekerja dengan start paralel.

Alasan yang disebutkan di atas menjadi pendorong untuk pengembangan QueueRunner - layanan yang memungkinkan Anda untuk menjalankan tes secara serempak tanpa memblokir CI. Untuk bekerja, ia membutuhkan tes dan uji APK, serta serangkaian tes. Setelah menerima data yang diperlukan, ia akan dapat mengatur proses berlari dalam antrian, mengalokasikan dan membebaskan sumber daya yang diperlukan. QueueRunner mengunduh hasil lari ke Jira dan Stash, dan juga mengirimkannya melalui surat dan di messenger.

QueueRunner memiliki aliran uji - ia memonitor siklus hidup tes. Aliran default yang kami gunakan sekarang terdiri dari lima langkah:

  1. Perangkat penerima. Pada titik ini, Devicemanager meminta melalui koordinator perangkat nyata atau virtual.
  2. . APK , – , .
  3. ,

Hasilnya, lima langkah sederhana adalah seluruh siklus hidup pengujian dalam layanan kami.



Apa manfaat yang diberikan QueueRunner kepada kami? Pertama, ia menggunakan semua sumber daya yang mungkin secara maksimal - dapat ditingkatkan ke seluruh tambak dan dengan cepat mendapatkan hasil. Kedua, dengan bonus, kami mendapat kesempatan untuk mengontrol urutan tes. Sebagai contoh, kita dapat menjalankan tes terpanjang atau paling bermasalah di awal dan dengan demikian mengurangi waktu yang dibutuhkan untuk menunggu mereka berjalan.

QueueRunner juga memungkinkan Anda membuat retret cerdas. Kami menyimpan semua data dalam basis data, sehingga kapan saja kami dapat melihat riwayat pengujian. Sebagai contoh, adalah mungkin untuk melihat rasio kelulusan ujian yang berhasil dan yang tidak berhasil serta memutuskan apakah, pada prinsipnya, layak untuk memulai kembali pengujian.

QueueRunner dan Devicemanager telah memberi kita kemampuan untuk beradaptasi dengan jumlah sumber daya. Sekarang kita dapat meningkatkan skala ke seluruh lahan, berkat penggunaan emulator, yaitu, jumlah perangkat virtual yang hampir tak terbatas memberi kita kesempatan untuk menjalankan lebih banyak pengujian, tetapi jika karena alasan tertentu sumber daya tidak tersedia, layanan akan menunggu mereka kembali dan tidak akan ada kehilangan peluncuran. Kami hanya menggunakan sumber daya yang tersedia untuk kami, oleh karena itu, setelah beberapa waktu hasilnya masih akan diperoleh dan pada saat yang sama CI tidak akan diblokir. Dan yang paling penting, infrastruktur pengujian dan pengujian sekarang terpisah.
Sekarang, untuk menjalankan tes di Android, Anda hanya perlu memberi kami APK uji dan daftar tes.

Kami telah menempuh perjalanan jauh dari pertanian Selenium di mesin virtual ke peluncuran tes Android di cloud. Namun, jalur ini belum selesai.

Proses pengembangan


Mari kita lihat bagaimana infrastruktur pengujian terkait dengan proses pengembangan dan bagaimana penguji dan pengembang melihatnya.

Tim Android kami menggunakan GitFlow standar:



Setiap fitur memiliki cabang sendiri. Pengembangan utama terjadi di cabang berkembang. Pengembang yang memutuskan untuk membuat fitur super baru memulai pengembangannya di cabangnya sendiri, sementara pengembang lain dapat bekerja di cabang lain secara paralel. Ketika seorang pengembang percaya bahwa kode yang idealnya indah, terbaik di dunia sudah siap dan perlu diluncurkan ke pengguna secepat mungkin, ia membuat permintaan menarik untuk dikembangkan, dan uji unit dan uji komponen secara otomatis dibangun dan diluncurkan. Secara bersamaan, APK dirakit, dikirim ke QueueRunner, dan tes end-to-end dijalankan. Setelah itu, hasil menjalankan tes datang ke pengembang.

Namun, ada kemungkinan besar bahwa setelah pembuatan cabang fitur dalam pengembangan, ada banyak komitmen. Ini berarti bahwa pengembangan mungkin tidak seperti dulu. Oleh karena itu, pra-penggabungan terjadi terlebih dahulu - kami menggabungkan berkembang menjadi cabang fitur saat ini, dan pada kondisi prematur inilah kami membangun, pengujian unit, pengujian komponen, ujung-ke-ujung, dan berdasarkan hasil ini kami membuat laporan. Dengan demikian, kami memahami bagaimana fungsionalnya fitur dalam versi pengembangan saat ini dan, jika semuanya baik-baik saja, maka fitur tersebut dikirimkan ke pengguna.



Pelaporan


Ini adalah bagaimana pelaporan Stash terlihat:



Bot kami pertama kali menulis bahwa tes telah dimulai, dan ketika mereka lulus, itu memperbarui pesan dan menambahkan berapa banyak yang telah lulus, berapa banyak yang telah jatuh, berapa banyak kesalahan yang diketahui, dan berapa banyak tes bersisik. Dia menulis hal yang sama di Jira, dan menambahkan tautan ke perbandingan peluncuran.

Beginilah perbandingan kedua peluncuran itu:



Di sini proses saat ini di cabang fitur dibandingkan dengan langkah terakhir dalam pengembangan. Ini berisi informasi tentang jumlah tes yang sedang dijalankan, masalah yang cocok, tes yang jatuh, dan tes Flaky yang tidak stabil yang berada dalam satu kondisi dan beralih ke yang lain.

Jika setidaknya satu tes unit atau lebih dari beberapa ambang batas uji end-to-end jatuh, maka gabungan akan diblokir.

Untuk memahami apakah tes jatuh secara stabil, kami membandingkan hash jejak jejak jatuh, sebelum mereka dibersihkan dari digit sebelumnya, hanya nomor baris yang tersisa. Jika hash cocok, maka ini adalah jatuh yang sama, jika mereka berbeda, maka kemungkinan besar jatuh akan berbeda.

Ringkasan


Sebagai hasilnya, kami menerapkan solusi yang stabil dan toleran terhadap kesalahan yang sesuai dengan infrastruktur kami. Kemudian infrastruktur yang dihasilkan diadaptasi untuk pengujian Android. Kami dibantu dalam hal ini oleh Manajer perangkat, yang membantu kami bekerja secara bersamaan dengan perangkat nyata, dan dengan perangkat virtual, serta QueueRunner, yang membantu kami memisahkan infrastruktur dan pengujian, dan tidak memblokir CI selama pengujian berlangsung.

Itu tampak seperti waktu uji coba selama satu minggu pada 2016 - dari lima puluh menit atau lebih.



Begini tampilannya:



Bagan ini menunjukkan proses yang berlangsung lebih dari 2 jam dari rata-rata hari kerja. Waktu berjalan dikurangi hingga maksimum 15 menit, jumlah lari meningkat tajam.

All Articles