Selamat siang Saya ingin memperkenalkan alat baru untuk pengujian ujung-ke-ujung dari layanan-mikro - Catcher

Kenapa harus tes?
Mengapa saya perlu pengujian e2e? Martin Fowler merekomendasikan untuk menghindari tes yang lebih sederhana.
Namun, semakin tinggi tes, semakin sedikit penulisan ulang. Tes unit hampir sepenuhnya ditulis ulang. Tes fungsional juga harus menghabiskan waktu Anda jika terjadi refactoring serius. Tes ujung ke ujung harus menguji logika bisnis, dan itu jarang berubah.
Selain itu, bahkan cakupan uji lengkap dari semua layanan Microsoft tidak menjamin interaksi yang benar. Pengembang mungkin salah mengimplementasikan protokol (kesalahan dalam nama / tipe data).
Atau terapkan fungsi baru dengan mengandalkan skema data dari dokumentasi, dan dapatkan kejutan pada lingkungan produk dalam bentuk kesalahan ketidaksesuaian skema: kekacauan dalam data atau seseorang lupa memperbarui skema data.
Dan tes dari masing-masing layanan yang terlibat akan berwarna hijau.
Mengapa pengujian otomatis?
Sungguh. Di tempat kerja saya sebelumnya, diputuskan bahwa menghabiskan waktu menggunakan tes otomatis terlalu lama, sulit, dan mahal. Sistemnya tidak besar (10-15 microservices dengan kafka biasa). CTO memutuskan bahwa "tes tidak penting, yang utama adalah sistem bekerja." Diuji secara manual pada beberapa lingkungan.
Bagaimana kelihatannya (proses umum):
- Setuju dengan pengembang lain (meluncurkan semua layanan microsoft yang berpartisipasi dalam fungsionalitas baru)
- Gulirkan semua layanan
- Terhubung ke kafka jarak jauh (dobel ssh dmz)
- Hubungkan ke k8s log
- Secara manual membentuk dan mengirim pesan kafka (terima kasih Tuhan json)
- Perhatikan log, mencoba memahami apakah itu berfungsi atau tidak.
Dan sekarang, sedikit lalat di salep dengan cokelat: sebagian besar tes diperlukan untuk membuat pengguna, karena menggunakan kembali yang sudah ada sulit.
Pertama, karena sistem terdistribusi, beberapa layanan memiliki database sendiri yang berisi informasi pengguna.
Kedua, kafka digunakan untuk penyimpanan data permanen. Yaitu bahkan jika informasi itu dihapus / diubah dalam database, layanan masih akan membacanya kembali saat reboot.
Seperti apa bentuk pendaftaran pengguna uji baru (kurang-lebih):
- Masukkan data apa saja (nama, surat, dll.)
- Memasukkan data pribadi (alamat, telepon, informasi pajak apa pun)
- Memasukkan data bank (sebenarnya, data bank)
- Jawab 20-40 pertanyaan (apakah Anda sudah merasakan sakit?)
- Pergi melalui identifikasi IDNow (terima kasih, mereka mematikannya di lingkungan dev, terima kasih, pada tahap itu sekitar 5 menit atau lebih, karena kotak pasir mereka kadang-kadang kelebihan beban)
- Pada langkah ini, membuka akun dalam sistem pihak ketiga diperlukan dan tidak ada yang dapat dilakukan melalui front-end. Anda harus pergi ssh ke Kafka dan bekerja sebagai server tiruan (mengirim pesan bahwa akun terbuka)
- Selanjutnya, Anda harus pergi ke front-end lain di akun pribadi moderator dan mengonfirmasi pengguna.
Super, pengguna terdaftar! Sekarang sedikit lalat di salep: beberapa tes membutuhkan lebih dari 1 pengguna tes. Dan terkadang tes gagal pertama kali.
Dan bagaimana verifikasi fungsi baru dan konfirmasi dari tim bisnis?
Semua hal yang sama perlu diulangi pada lingkungan berikut.
Tak perlu dikatakan, setelah beberapa saat Anda mulai merasa seperti monyet, yang hanya melakukan apa yang ditekan, mendaftar pengguna.
Beberapa pengembang lain (biasanya ujung depan) memiliki masalah koneksi ke kafka. Dan dengan bug di terminal dengan string 80+ karakter (tidak semua orang tahu tentang tmux).
Pro :
- tidak perlu mengkonfigurasi / menulis apa pun. Tes langsung pada lingkungan yang sedang berjalan.
- tidak memerlukan kualifikasi tinggi (spesialis yang lebih murah dapat melakukannya)
Cons :
- membutuhkan banyak waktu (semakin jauh, semakin banyak)
- biasanya hanya fungsionalitas baru yang diuji (tidak jelas apakah yang sudah ada rusak)
- Seringkali, pengembang yang terampil terlibat dalam pengujian manual (spesialis mahal melakukan pekerjaan murah).
Bagaimana cara mengotomatisasi?
Jika Anda membaca ini dengan menganggukkan kepala dan berkata: "Ya, ini adalah proses yang hebat, kalian tahu apa yang mereka lakukan," maka Anda tidak akan tertarik.
Tes e2e buatan rumah terdiri dari dua jenis dan tergantung pada programmer mana yang lebih bebas:
- backend yang hidup di lingkungan pengujian Anda. Ini melindungi logika pengujian, yang berkedut melalui titik akhir. Bahkan dapat sebagian otomatis karena interaksi dengan CI.
- Sebuah skrip dengan logika kabel yang sama. Satu-satunya perbedaan adalah Anda harus pergi ke suatu tempat dan menjalankannya dari sana. Jika Anda mempercayai CI Anda, maka Anda bahkan dapat menjalankannya secara otomatis.
Kedengarannya bagus. Masalah?
Ya, tes semacam itu ditulis berdasarkan apa yang diketahui oleh orang yang menulisnya. Biasanya, ini adalah bahasa scripting seperti menggosok atau python, yang memungkinkan Anda untuk dengan cepat dan mudah menulis hal semacam ini. Namun, kadang-kadang Anda dapat menemukan sekelompok skrip bash, C atau sesuatu yang lebih eksotis (saya menghabiskan seminggu menyalin sepeda saya pada skrip bash ke python karena skrip tidak lagi dapat diperluas dan tidak ada yang benar-benar tahu cara kerjanya dan apa yang mereka uji) .
Contoh proyek di sini
Pro :
Cons :
- persyaratan kualifikasi tambahan untuk pengembang dimungkinkan (jika mereka berkembang di Jawa, dan tes ditulis dengan Python)
- menulis kode untuk menguji kode tertulis (siapa yang akan menguji tes?)
Apakah ada yang siap?
Tentu saja, lihat saja ke arah BDD . Ada Mentimun , ada Gauge .
Singkatnya - pengembang menjelaskan skenario bisnis dalam bahasa khusus, lalu mengimplementasikan langkah-langkah script dalam kode. Bahasa ini umumnya dapat dibaca manusia dan diasumsikan tidak hanya pengembang, tetapi juga manajer proyek akan membaca / menulisnya.
Script bersama dengan implementasi langkah-langkah juga dalam proyek terpisah dan dijalankan oleh produk pihak ketiga (Mentimun / Gauge / ...).
Scriptnya terlihat seperti ini:
Customer sign-up ================ * Go to sign up page Customer sign-up ---------------- tags: sign-up, customer * Sign up a new customer with name "John" email "jdoe@test.de" and "password" * Check if the sign up was successful
Dan implementasi:
@Step("Sign up as <customer> with email <test@example.com> and <password>") public void signUp(String customer, String email, String password) { WebDriver webDriver = Driver.webDriver; WebElement form = webDriver.findElement(By.id("new_user")); form.findElement(By.name("user[username]")).sendKeys(customer); form.findElement(By.name("user[email]")).sendKeys(email); form.findElement(By.name("user[password]")).sendKeys(password); form.findElement(By.name("user[password_confirmation]")).sendKeys(password); form.findElement(By.name("commit")).click(); } @Step("Check if the sign up was successful") public void checkSignUpSuccessful() { WebDriver webDriver = Driver.webDriver; WebElement message = webDriver.findElements(By.className("message")); assertThat(message.getText(), is("You have been signed up successfully!")); }
Proyek lengkap di sini
Pro :
- logika bisnis dijelaskan dalam bahasa yang dapat dibaca manusia dan disimpan di satu tempat (dapat digunakan sebagai dokumentasi)
- solusi siap pakai digunakan, pengembang hanya perlu tahu cara menggunakannya
Cons :
- manajer tidak akan membaca dan menulis skrip
- Anda harus mengikuti spesifikasi dan implementasinya (dan ini adalah penulisan kode dan spesifikasi pengeditan)
Nah, lalu mengapa Catcher?
Tentu saja untuk mempermudah prosesnya.
Pengembang hanya menulis skrip di json / yaml, dan Catcher mengeksekusinya. Script terdiri dari langkah-langkah yang dieksekusi berurutan, misalnya:
steps: - http: post: url: '127.0.0.1/save_data' body: {key: '1', data: 'foo'} - postgres: request: conf: 'dbname=test user=test host=localhost password=test' query: 'select * from test where id=1'
Catcher mendukung templat jinja2, sehingga Anda dapat menggunakan variabel alih-alih nilai kabel dalam contoh di atas. Variabel global dapat disimpan dalam file inventaris (seperti dalam ansambel), ditarik dari lingkungan dan yang baru terdaftar:
variables: bonus: 5000 initial_value: 1000 steps: - http: post: url: '{{ user_service }}/sign_up' body: {username: 'test_user_{{ RANDOM_INT }}', data: 'stub'} register: {user_id: '{{ OUTPUT.uuid }}' - kafka: consume: server: '{{ kafka }}' topic: '{{ new_users_topic }}' where: equals: {the: '{{ MESSAGE.uuid }}', is: '{{ user_id }}'} register: {balance: '{{ OUTPUT.initial_balance }}'}
Selain itu, Anda dapat menjalankan langkah-langkah pengujian:
- check: # check user's initial balance equals: {the: '{{ balance }}', is: '{{ initial_value + bonus }}'}
Anda juga dapat menjalankan beberapa skrip dari skrip lain, yang memiliki efek sangat baik pada kebersihan dan penggunaan kembali kode (termasuk peluncuran hanya sebagian langkah melalui sistem tag, peluncuran tertunda, roti dll).
include: file: register_user.yaml as: sign_up steps: # .... some steps - run: include: sign_up # .... some steps
Memasukkan dan menggunakan skrip dapat memecahkan masalah menunggu sumber daya (tunggu layanan saat dimulai).
Selain langkah - langkah bawaan yang sudah jadi dan repositori tambahan), dimungkinkan untuk menulis modul Anda dengan python (hanya mewarisi dari ExternalStep ) atau dalam bahasa lain:
dan gunakan:
--- variables: one: 1 two: 2 steps: - math: add: {the: '{{ one }}', to: '{{ two }}'} register: {sum: '{{ OUTPUT }}'}
Script ditempatkan di file buruh pelabuhan dan dijalankan melalui CI.
Gambar ini juga dapat digunakan di Marathon / K8 untuk menguji lingkungan yang ada. Saat ini saya sedang mengerjakan backend (mirip dengan AnsibleTower) untuk membuat proses pengujian lebih mudah dan lebih nyaman.
Pro :
- tidak perlu menulis kode (hanya untuk modul-modul khusus)
- berpindah lingkungan melalui file inventaris (seperti pada ensemble)
- Anda dapat menggunakan modul Anda sendiri (dalam bahasa apa pun, bahkan sh)
Cons :
- sintaks yang tidak dapat dibaca manusia (dibandingkan dengan alat BDD)
Alih-alih sebuah kesimpulan
Ketika saya menulis alat ini, saya hanya ingin mengurangi waktu yang biasanya saya habiskan untuk tes. Kebetulan setiap perusahaan baru harus menulis (atau menulis ulang) sistem seperti itu.
Namun, alat itu ternyata lebih fleksibel daripada yang saya harapkan. Jika seseorang tertarik pada artikel (atau alat itu sendiri), saya dapat memberi tahu Anda cara menggunakan Catcher untuk mengatur migrasi terpusat dan memperbarui sistem layanan-mikro.
Pembaruan
Seperti yang saya tunjukkan dalam komentar, topiknya tidak diungkapkan.
Saya akan mencoba untuk menunjukkan di sini tesis yang paling kontroversial.
- tes ujung ke ujung bukan tes unit. Saya sudah merujuk ke M. Fowler dalam artikel ini. Tes unit dalam proyek backend tes (direktori
tests
standar) dan dijalankan setiap kali kode berubah menjadi CI. Dan tes e2e adalah proyek terpisah, biasanya memakan waktu lebih lama, menguji interaksi semua layanan yang berpartisipasi dan tidak tahu apa-apa tentang kode proyek Anda (kotak hitam). - Anda sebaiknya tidak menggunakan tes Catcher untuk integrasi (dan di bawah). Itu mahal. Jauh lebih cepat untuk menulis tes pada YP Anda untuk backend saat ini. Anda memerlukan pengujian ujung-ke-ujung hanya jika logika bisnis Anda tersebar di 2 atau lebih layanan.
- Catcher juga merupakan BDD. Dari sudut pandang saya, keuntungan utama dari Gauge / Mentimun adalah modul yang sudah jadi dan kemudahan menambahkannya. Idealnya, hanya tes yang ditulis. Di perusahaan terakhir, saya menulis semua 4 tes pada komponen standar, tanpa memprogram apa pun. Dengan demikian, persyaratan kualifikasi (dan harga spesialis seperti itu) akan lebih rendah. Hanya pengetahuan tentang json / yaml dan kemampuan membaca spesifikasi yang dibutuhkan.
- Untuk menulis tes Catcher, Anda harus belajar Catcher-DSL. Sayangnya, itu benar. Awalnya saya ingin membuat tes menulis sendiri, langsung dari mikrofon. Tapi kemudian saya berpikir bahwa mereka kemudian akan memecat saya sebagai tidak perlu;) Seperti yang disebutkan di atas - Catcher DSL adalah standar json / yaml dan spesifikasi langkah. Tidak ada yang secara fundamental baru.
- Anda dapat menggunakan teknologi standar dan menulis sendiri. Namun, kita berbicara tentang layanan mikro. Ini adalah sejumlah besar berbagai teknologi dan senjata nuklir dan sejumlah besar tim. Dan jika untuk perintah java junit + testcontainers adalah pilihan yang jelas, tim erlang akan memilih sesuatu yang lain. Di perusahaan besar dengan 30+ tim di puncak, mereka akan memutuskan bahwa semua tes harus diserahkan ke tim infrastruktur / qa baru. Bisakah Anda bayangkan betapa bahagianya mereka di kebun binatang ini?
- Jika Anda memiliki tes 4-5 e2e, maka Anda dapat menulis semuanya dalam bahasa skrip apa pun dan melupakannya. Namun, jika logikanya berubah dari waktu ke waktu, maka setelah 2-4 tahun Anda harus melakukan refactor, mendistribusikan secara langsung logika bisnis dari tes dan implementasi metode akses ke komponen yang diuji. Jadi pada akhirnya Anda menulis Catcher Anda, hanya saja tidak begitu fleksibel. Butuh 4 implementasi untuk memahami hal ini;)