Baik, buruk, jahat - pengujian dalam proyek pemula

Kata Pengantar: universitas menerima tugas - untuk mengumpulkan tim scrum, memilih proyek dan mengerjakannya selama satu semester. Tim kami memilih pengembangan aplikasi web (reaksi + labu). Pada artikel ini saya akan mencoba memberi tahu Anda apa tes yang seharusnya dan menganalisis apa yang kami lakukan di backend.



Harapan


Tes diperlukan, pertama-tama, untuk meyakinkan semua orang (termasuk diri kita sendiri) bahwa program berperilaku sebagaimana mestinya dalam situasi pengujian . Kedua, mereka memastikan kinerja kode yang dicakup oleh tes di masa depan. Tes menulis adalah proses yang berguna, karena dalam prosesnya Anda dapat sering tersandung pada masalah, mengingat beberapa kasus ekstrim, melihat masalah dengan antarmuka, dll.


Saat mengembangkan sistem apa pun, Anda perlu mengingat setidaknya tiga jenis tes:


  • Tes unit adalah tes yang memverifikasi bahwa fungsi melakukan apa yang mereka butuhkan.
  • Tes integrasi adalah tes yang memverifikasi bahwa beberapa fungsi secara bersamaan melakukan hal yang benar.
  • Tes sistem adalah tes yang memverifikasi bahwa seluruh sistem melakukan apa yang diperlukan.

Di salah satu posting dari google, sebuah tabel diterbitkan dengan deskripsi dari tiga jenis tes. "Kecil", "Sedang" dan "Besar".



Tes unit


Tes unit sesuai dengan tes kecil - tes harus cepat dan hanya memeriksa kebenaran bagian tertentu dari program. Mereka tidak boleh mengakses database, tidak boleh bekerja di lingkungan multi-threaded yang kompleks. Mereka mengontrol kepatuhan dengan spesifikasi / standar, seringkali mereka memiliki peran tes regresi .


Tes integrasi


Tes integrasi adalah tes yang dapat mempengaruhi beberapa modul dan fungsi. Tes semacam itu membutuhkan lebih banyak waktu dan mungkin memerlukan lingkungan khusus. Mereka diperlukan untuk memastikan bahwa masing-masing modul dan fungsi dapat bekerja satu sama lain. Yaitu unit test memverifikasi kesesuaian antarmuka nyata dengan yang diharapkan, dan tes integrasi - bahwa fungsi dan modul saling berinteraksi dengan benar.


Tes sistem


Ini adalah tingkat pengujian otomatis tertinggi. Tes sistem memverifikasi bahwa seluruh sistem berfungsi, bahwa bagian-bagiannya melakukan tugasnya dan dapat berinteraksi dengan benar.


Mengapa melacak tipe


Biasanya, dengan pertumbuhan proyek, basis kode juga akan tumbuh. Durasi pemeriksaan otomatis akan meningkat, mendukung sejumlah besar uji integrasi dan sistem akan menjadi semakin sulit. Oleh karena itu, tantangan bagi pengembang adalah untuk meminimalkan tes yang diperlukan. Untuk melakukan ini, coba gunakan unit test jika memungkinkan dan kurangi integrasi menggunakan "mock" (mock).


Realita


Tes API Khas


def test_user_reg(client): return json.loads( client.post(url, json=data, content_type='application/json').data ) response = client.post('api/user.reg', json={ 'email': 'name@mail.ru', 'password': 'password1', 'first_name': 'Name', 'last_name': 'Last Name' }) data = json.loads(response.data) assert data['code'] == 0 

Dari dokumentasi resmi labu, kami mendapatkan resep yang sudah jadi untuk menginisialisasi aplikasi dan membuat database. Ini adalah pekerjaan dengan database. Ini bukan tes unit, tetapi bukan tes sistem. Ini adalah tes integrasi yang menggunakan aplikasi tes database.


Mengapa integrasi daripada modular? Karena dalam pemrosesan kueri, interaksi dilakukan dengan labu, dengan ORM, dengan logika bisnis kami. Handler bertindak sebagai tautan pemersatu bagian lain dari proyek, jadi menulis unit test untuk mereka tidak terlalu mudah (Anda perlu mengganti database dengan ejekan, logika internal) dan tidak terlalu praktis (tes integrasi akan memeriksa aspek serupa - "apakah fungsi yang diperlukan dipanggil?", " Apakah data diterima dengan benar? ", Dll.).


Nama dan pengelompokan tes


 def test_not_empty_errors(): assert validate_not_empty('email', '') == ('email is empty',) assert validate_not_empty('email', ' ') == ('email is empty',) assert validate_email_format('email', "") == ('email is empty',) assert validate_password_format('pass', "") == ('pass is empty',) assert validate_datetime('datetime', "") == ('datetime is empty',) 

Dalam tes ini, semua kondisi untuk tes "kecil" terpenuhi - perilaku fungsi tanpa dependensi diperiksa untuk kesesuaian dengan yang diharapkan. Namun desainnya menimbulkan pertanyaan.


Merupakan praktik yang baik untuk menulis tes yang berfokus pada aspek tertentu dari program. Dalam contoh ini, ada berbagai fungsi - validate_password_format , validate_password_format , validate_datetime . Pengelompokan pemeriksaan tidak didasarkan pada hasil, tetapi pada objek pengujian.


Nama tes ( test_not_empty_errors ) tidak menjelaskan objek pengujian (metode mana yang sedang diuji), itu hanya menggambarkan hasilnya (kesalahan tidak kosong). Metode ini harus disebut test__validate_not_empty__error_on_empty . Nama ini menjelaskan apa yang sedang diuji dan hasil apa yang diharapkan. Ini berlaku untuk hampir setiap nama uji dalam proyek karena fakta bahwa tidak ada waktu yang diambil untuk membahas konvensi penamaan tes.


Tes regresi


 def test_datetime_errors(): assert validate_datetime('datetime', '0123-24-31T;431') == ('datetime is invalid',) assert validate_datetime('datetime', '2018-10-18T20:21:21+-23:1') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-13-20T20:20:20+20:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-02-29T20:20:20+20:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-12-20T25:20:20+20:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-12-20T20:61:20+22:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-12-20T20:20:61+20:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-12-20T20:20:20+25:20') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-12-20T20:20:20+20:61') == ('datetime is invalid',) assert validate_datetime('datetime', '2015-13-35T25:61:61+61:61') == ('datetime is invalid',) 

Tes ini awalnya terdiri dari dua pernyataan pertama. Setelah itu, "bug" ditemukan - alih-alih memeriksa tanggal, hanya ekspresi reguler yang diperiksa, mis. 9999-99-99 dianggap sebagai tanggal normal. Pengembang memperbaikinya. Secara alami, setelah memperbaiki bug, Anda perlu menambahkan tes untuk mencegah regresi di masa depan. Alih-alih menambahkan tes baru untuk menulis mengapa tes ini ada, cek telah ditambahkan ke tes ini.


Apa yang harus disebut tes baru untuk menambah verifikasi? Mungkin test__validate_datetime__error_on_bad_datetime .


Mengabaikan alat


 def test_get_providers(): class Tmp: def __init__(self, id_external, token, username): self.id_external = id_external self.token = token self.username = username ... 

Tmp ? Ini adalah substitusi untuk objek yang tidak digunakan dalam tes ini. Pengembang sepertinya tidak tahu tentang keberadaan @patch dan MagicMock dari unittest.mock . Tidak perlu menyulitkan kode dengan memecahkan masalah secara naif ketika ada alat yang lebih memadai.


Ada tes yang menginisialisasi layanan (dalam database), menggunakan konteks aplikasi.


 def test_get_posts(client): def fake_request(*args, **kwargs): return [one, two] handler = VKServiceHandler() handler.request = fake_request services_init() with app.app_context(): posts = handler.get_posts(None) assert len(posts) == 2 

Anda dapat mengecualikan basis data dan konteks dari tes dengan hanya menambahkan satu @patch .


 @patch("mobius.services.service_vk.Service") def test_get_posts(mock): def fake_request(*args, **kwargs): return [one, two] handler = VKServiceHandler() handler.request = fake_request posts = handler.get_posts(None) assert len(posts) == 2 

Ringkasan


  • Untuk mengembangkan perangkat lunak yang berkualitas, Anda perlu menulis tes. Minimal, untuk memastikan Anda menulis apa yang Anda butuhkan.
  • Untuk sistem informasi besar, pengujian bahkan lebih penting - tes ini memungkinkan Anda untuk menghindari perubahan antarmuka yang tidak diinginkan atau mengembalikan bug.
  • Agar tes tertulis tidak berubah menjadi banyak metode aneh seiring waktu, Anda perlu memperhatikan konvensi penamaan tes, mematuhi praktik yang baik, dan meminimalkan tes.
  • Tes unit bisa menjadi alat yang hebat selama pengembangan. Mereka dapat dijalankan setelah setiap perubahan kecil untuk memastikan tidak ada yang rusak.

Poin yang sangat penting adalah bahwa tes tidak menjamin ketersediaan atau tidak adanya bug. Tes memastikan bahwa hasil nyata dari program (atau bagian dari itu) diharapkan. Dalam hal ini, verifikasi hanya terjadi untuk aspek-aspek yang tesnya ditulis. Karena itu, ketika membuat produk yang berkualitas, kita tidak boleh lupa tentang jenis pengujian lainnya.

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


All Articles