Memperkenalkan Pengujian dengan Python. Bagian 2

Halo semuanya!

Kami melanjutkan artikel tentang kenalan dengan pengujian di Python, yang kami siapkan untuk Anda sebagai bagian dari kursus Pengembang Python kami.

Pengujian untuk Kerangka Web Django dan Flask

Jika Anda menulis tes untuk aplikasi web menggunakan salah satu kerangka kerja populer, misalnya, Django atau Labu, maka ada baiknya mengingat perbedaan penting dalam menulis dan menjalankan tes tersebut.

Bagaimana Mereka Berbeda dari Aplikasi Lain

Pikirkan kode yang ingin Anda uji dalam aplikasi web. Semua rute, pandangan dan model memerlukan banyak impor dan pengetahuan tentang kerangka kerja yang digunakan.
Ini mirip dengan pengujian mobil, yang telah dibahas di bagian pertama tutorial: sebelum melakukan tes sederhana, seperti memeriksa lampu depan, Anda harus menyalakan komputer di mobil.

Django dan Flask menyederhanakan tugas ini dan menyediakan kerangka kerja uji coba yang paling tidak berbasis Anda dapat terus menulis tes dengan cara biasa, tetapi menjalankannya sedikit berbeda.



Bagaimana cara menggunakan Pelaksana Tes Django

Template Django startapp membuat file tests.py di direktori aplikasi Anda. Jika belum ada, buat dengan konten berikut:

from django.test import TestCase class MyTestCase(TestCase): # Your test methods 

Perbedaan utama dari contoh sebelumnya adalah bahwa Anda perlu mewarisi dari django.test.TestCase , bukan unittest.TestCase . API kelas-kelas ini adalah sama, tetapi kelas Testang Django mengatur segalanya untuk pengujian.

Untuk menjalankan test suite, gunakan tes manage.py alih-alih unittest di baris perintah:

 $ python manage.py test 

Jika Anda memerlukan beberapa file uji, ganti tests.py dengan folder tes, masukkan file kosong bernama __init__.py dan buat file test_*.py . Django akan mendeteksi mereka dan mengeksekusi.

Informasi lebih lanjut tersedia di situs dokumentasi Django .

Cara Menggunakan Unittest dan Labu

Untuk bekerja dengan Flask, aplikasi harus diimpor dan dimasukkan ke mode uji. Anda dapat membuat klien uji dan menggunakannya untuk mengirim permintaan ke rute apa pun di aplikasi Anda.

Klien uji dipakai di metode setUp kasus uji Anda. Dalam contoh berikut, my_app adalah nama aplikasi. Jangan khawatir jika Anda tidak tahu apa yang dilakukan pengaturan. Kami akan melihat lebih dekat pada bagian "Script Pengujian Lebih Lanjut".
Kode dalam file tes akan terlihat seperti ini:

 import my_app import unittest class MyTestCase(unittest.TestCase): def setUp(self): my_app.app.testing = True self.app = my_app.app.test_client() def test_home(self): result = self.app.get('/') # Make your assertions 

Anda kemudian dapat menjalankan test case menggunakan python -m unittest discover.

Informasi lebih lanjut tersedia di situs dokumentasi Flask.

Script Pengujian Lebih Lanjut

Sebelum Anda mulai membuat tes untuk aplikasi Anda, ingatlah tiga langkah utama dari setiap tes:

  1. Pembuatan parameter input;
  2. Eksekusi kode, menerima data output;
  3. Perbandingan data keluaran dengan hasil yang diharapkan;

Ini bisa lebih rumit daripada menciptakan nilai statis untuk data sumber seperti string atau angka. Terkadang aplikasi Anda membutuhkan instance kelas atau konteks. Apa yang harus dilakukan dalam kasus ini?

Data yang Anda buat sebagai sumber disebut fixture. Membuat dan menggunakan kembali perlengkapan adalah praktik yang umum.

Menjalankan pengujian yang sama beberapa kali dengan nilai yang berbeda untuk mengantisipasi hasil yang sama disebut parameterisasi.

Menangani Kegagalan yang Diharapkan

Sebelumnya, ketika kami menyusun daftar skrip untuk sum() pengujian sum() , muncul pertanyaan: apa yang terjadi ketika kami memberikan nilai yang buruk, misalnya, satu integer atau string?

Dalam hal ini, diharapkan sum() akan menimbulkan kesalahan. Jika kesalahan terjadi, tes akan gagal.

Ada cara khusus untuk menangani kesalahan yang diharapkan. Anda bisa menggunakan .assertRaises() sebagai manajer konteks, dan kemudian melakukan langkah-langkah pengujian di dalam blok with :

 import unittest from my_sum import sum class TestSum(unittest.TestCase): def test_list_int(self): """ ,       """ data = [1, 2, 3] result = sum(data) self.assertEqual(result, 6) def test_list_fraction(self): """ ,       """ data = [Fraction(1, 4), Fraction(1, 4), Fraction(2, 5)] result = sum(data) self.assertEqual(result, 1) def test_bad_type(self): data = "banana" with self.assertRaises(TypeError): result = sum(data) if __name__ == '__main__': unittest.main() 

Kasing uji ini akan diteruskan hanya jika sum(data) melempar TypeError. Anda dapat mengganti TypeError dengan jenis pengecualian lainnya.

Isolasi Perilaku Aplikasi

Di bagian akhir tutorial, kami berbicara tentang efek samping. Mereka mempersulit pengujian unit, karena setiap uji coba dapat menghasilkan hasil yang berbeda atau lebih buruk - satu tes dapat mempengaruhi keadaan seluruh aplikasi dan menyebabkan tes lain gagal!

Ada beberapa teknik sederhana untuk menguji bagian-bagian aplikasi dengan banyak efek samping:

  • Refactoring kode sesuai dengan Prinsip Tanggung Jawab Tunggal;
  • Mengejek semua metode dan panggilan fungsi untuk menghilangkan efek samping;
  • Menggunakan tes integrasi daripada tes unit untuk fragmen aplikasi ini.
  • Jika Anda tidak terbiasa dengan moking, lihat beberapa contoh Pengujian Python CLI yang hebat .

Tes Integrasi Penulisan

Sejauh ini, kami lebih memperhatikan unit test. Pengujian unit adalah cara yang bagus untuk membuat kode yang dapat diprediksi dan stabil. Tetapi pada akhirnya, aplikasi Anda akan berfungsi saat startup!

Diperlukan pengujian integrasi untuk memverifikasi kolaborasi beberapa komponen aplikasi. Pengujian semacam itu mungkin mengharuskan memerankan peran pembeli atau pengguna:

  • Sebut API HTTP REST;
  • Panggilan Python API;
  • Panggilan layanan web;
  • Jalankan baris perintah.

Semua jenis tes integrasi ini dapat ditulis dengan cara yang sama seperti tes unit, mengikuti template Parameter Input, Eksekusi, Persetujuan. Perbedaan yang paling signifikan adalah bahwa tes integrasi secara bersamaan menguji lebih banyak komponen, yang berarti mereka akan menyebabkan lebih banyak efek samping daripada tes unit. Selain itu, tes integrasi memerlukan lebih banyak perlengkapan, seperti database, soket jaringan, atau file konfigurasi.

Oleh karena itu, disarankan untuk memisahkan tes unit dan tes integrasi. Membuat fixture untuk yang terintegrasi, misalnya, database pengujian atau test case sendiri, membutuhkan lebih banyak waktu daripada melakukan tes unit, jadi Anda harus melakukan tes integrasi sebelum mulai berproduksi alih-alih menjalankannya setiap kali Anda berkomitmen.

Cara paling sederhana untuk memisahkan tes unit dan integrasi adalah dengan meletakkannya di folder yang berbeda.

project/
β”‚
β”œβ”€β”€ my_app/
β”‚ └── __init__.py
β”‚
└── tests/
|
β”œβ”€β”€ unit/
| β”œβ”€β”€ __init__.py
| └── test_sum.py
|
└── integration/
β”œβ”€β”€ __init__.py
└── test_integration.py


Anda dapat menjalankan kelompok tes tertentu dengan berbagai cara. Bendera untuk menentukan direktori sumber, -s, dapat ditambahkan ke unittest find dengan jalur yang berisi tes:

 $ python -m unittest discover -s tests/integration 

unittest akan menampilkan semua hasil dalam direktori tes / integrasi.

Menguji Aplikasi yang Berorientasi Data

Banyak tes integrasi memerlukan data backend, seperti database dengan nilai tertentu. Misalkan Anda memerlukan tes untuk memverifikasi operasi aplikasi yang benar dengan lebih dari 100 pelanggan dalam database, atau untuk memverifikasi kebenaran tampilan halaman pesanan, bahkan jika semua nama barang dalam bahasa Jepang.

Jenis tes integrasi ini akan tergantung pada berbagai perlengkapan tes untuk memastikan pengulangan dan prediktabilitasnya.

Data uji harus disimpan dalam folder fixture di dalam direktori tes integrasi untuk menekankan β€œkemampuan uji” mereka. Kemudian dalam tes Anda dapat memuat data dan menjalankan tes.

Berikut adalah contoh dari struktur data yang terdiri dari file JSON:

project/
β”‚
β”œβ”€β”€ my_app/
β”‚ └── __init__.py
β”‚
└── tests/
|
└── unit/
| β”œβ”€β”€ __init__.py
| └── test_sum.py
|
└── integration/
|
β”œβ”€β”€ fixtures/
| β”œβ”€β”€ test_basic.json
| └── test_complex.json
|
β”œβ”€β”€ __init__.py
└── test_integration.py


Dalam kasus pengujian, Anda dapat menggunakan metode .setUp () untuk memuat data uji dari file fixture dengan cara yang dikenal dan menjalankan beberapa tes dengan data ini. Ingatlah bahwa Anda dapat menyimpan beberapa test case dalam satu file Python, unittest akan menemukan dan menjalankannya. Anda dapat memiliki satu test case untuk setiap set data pengujian:

 import unittest class TestBasic(unittest.TestCase): def setUp(self): # Load test data self.app = App(database='fixtures/test_basic.json') def test_customer_count(self): self.assertEqual(len(self.app.customers), 100) def test_existence_of_customer(self): customer = self.app.get_customer(id=10) self.assertEqual(customer.name, "Org XYZ") self.assertEqual(customer.address, "10 Red Road, Reading") class TestComplexData(unittest.TestCase): def setUp(self): # load test data self.app = App(database='fixtures/test_complex.json') def test_customer_count(self): self.assertEqual(len(self.app.customers), 10000) def test_existence_of_customer(self): customer = self.app.get_customer(id=9999) self.assertEqual(customer.name, u"γƒγƒŠγƒŠ") self.assertEqual(customer.address, "10 Red Road, Akihabara, Tokyo") if __name__ == '__main__': unittest.main() 

Jika aplikasi Anda bergantung pada data dari lokasi jarak jauh, seperti API jarak jauh, pastikan tes dapat diulang. Pengembangan mungkin tertunda karena tes yang gagal saat menonaktifkan API dan masalah komunikasi. Dalam kasus seperti itu, lebih baik menyimpan perlengkapan jarak jauh secara lokal untuk dipanggil kembali dan dikirim ke aplikasi.

Pustaka requests memiliki paket respons gratis yang memungkinkan Anda membuat perlengkapan respons dan menyimpannya dalam folder uji. Cari tahu lebih lanjut di halaman GitHub mereka .

Bagian selanjutnya adalah tentang pengujian di beberapa lingkungan dan pengujian otomasi.

AKHIR

Komentar / pertanyaan selalu diterima. Di sini atau pergi ke Stas pada hari terbuka .

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


All Articles