Pengujian sistem mengacu pada pengujian SDV yang dibuat menggunakan Framework Pengujian SDV.
Pembuatan pengujian
Lokasi pengujian
<test_repository_root>/sample_tests<test_repository_root>/e2e_tests<test_repository_root>/long_running_tests<test_repository_root>/performance_tests<test_repository_root>/hardware
Menguji file
README.md: Semua pengujian harus menyertakan deskripsi tujuan pengujian dan cara menjalankan pengujian.File pengujian: Semua pengujian mengikuti struktur yang serupa:
"""SDV Name Test"""
from sdv_test_fw.test_execution import sdv_base_test, sdv_test_runner
class SdvTypeNameTest(sdv_base_test.SdvBaseTestClass):
def setup_class(self):
# Setup code. Executed only once at the beginning of the test.
super().setup_class()
self.sdv_device1 = self.get_device('device1')
self.sdv_device2 = self.get_device('device2')
...
# Remove if not needed.
def setup_test(self):
super().setup_test()
# Setup code. Executed before every test case.
# Remove override if not needed.
# Remove if not needed.
def teardown_test(self):
# Cleanup code. Executed after every test case.
super().teardown_test()
# Remove if not needed.
def teardown_class(self):
# Cleanup code. Executed once at the end of the test.
super().teardown_class()
def test_name_case1(self):
# Test case step
# Test case verification
def test_name_case2(self):
# Test case step
# Test case verification
if __name__ == '__main__':
# Start Test Execution Using SDV Test Framework
sdv_test_runner.run()
- File build:
Android.bp. Struktur filenya adalah sebagai berikut:
python_test_host {
name: "SdvTypeNameTest", // Should match the name of the test class.
main: "sdv_type_name_test.py",
srcs: [
"sdv_type_name_test.py",
],
data: [
":sdv_test_fw_device_configs",
],
test_options: {
unit_test: false,
},
defaults: [
"sdv_test_fw_defaults",
],
test_config_template: ":<DEFAULT_TEMPLATE_NAME>",
}
Konvensi penamaan
Untuk mengidentifikasi dan menemukan berbagai jenis pengujian, pengujian harus dibuat dengan mengikuti konvensi penamaan tertentu.
Pengujian contoh
Nama file:
sdv_sample_<NAME>_test.pyNama class:
SdvSampleNameTest
Pengujian E2E
Nama file:
sdv_e2e_<NAME>_test.pyNama class:
SdvE2ENameTest
Pengujian yang berjalan lama
Nama file:
sdv_long_running_<NAME>_test.pyNama class:
SdvLongRunningNameTest
Pengujian performa
Nama file:
sdv_performance_<NAME>_test.pyNama class:
SdvPerformanceNameTest
Pengujian hardware
Nama file:
sdv_hw_<NAME>_test.pyNama class:
SdvHWNameTest
Panduan kode
Bagian ini memberikan panduan dan praktik terbaik untuk menulis Pengujian Sistem SDV.
Python dan Mobly
Pelajari panduan gaya Python dan praktik terbaik Mobly, serta pertimbangkan rekomendasi khusus SDV berikut:
Hindari penggunaan impor Mobly secara langsung, kecuali untuk pernyataan. Framework Pengujian SDV dibuat berdasarkan hal tersebut dengan fokus pada SDV.
Pernyataan: Gunakan pernyataan Mobly secara langsung.
Pengujian SDV
Bagian berikut menguraikan panduan dan praktik terbaik khusus untuk mengembangkan pengujian dalam Framework Pengujian SDV.
Penyiapan dan pembersihan
Kode penyiapan dan pembersihan harus berada di luar kasus pengujian. Metode teardown dipanggil meskipun pengujian gagal, untuk melakukan pembersihan perangkat yang tepat.
Lokasi kode penyiapan dan teardown bergantung pada kebutuhan spesifik pengujian, meskipun pengujian terganggu:
- Untuk menjalankan hanya sekali di awal dan akhir seluruh pengujian, gunakan
setup_classdanteardown_class. Misalnya, dapatkan perangkat, tetapkan nilai variabel atau status yang tidak berubah di antara kasus pengujian, konfigurasi properti perangkat umum, atau tetapkan flag.
def setup_class(self):
super().setup_class()
# setup code
def teardown_class(self):
# teardown code
super().teardown_class()
- Untuk menjalankan di antara kasus pengujian, sebelum dan setelah setiap kasus pengujian. Misalnya, sesi interaktif atau eksekusi layanan umum.
def setup_test(self):
super().setup_test()
# setup code
def teardown_test(self):
# teardown code
super().teardown_test()
Kasus pengujian dengan parameter
Gunakan kasus pengujian dengan parameter jika langkah-langkahnya sama di berbagai kasus pengujian untuk menghindari pengulangan kode.
from absl.testing import parameterized
@parameterized.named_parameters(
{
'testcase_name': 'ab',
'input1': 'a',
'input2': 'b',
},
{
'testcase_name': 'cd',
'input1': 'c',
'input2': 'd',
},
)
def test_name(self, input1, input2):
# test
Contoh ini membuat dua kasus pengujian test_name_ab dan test_name_cd.
Satu kasus pengujian untuk verifikasi perilaku
Kasus pengujian harus ringkas dan berfokus pada satu perilaku tertentu. Jika beberapa perilaku memiliki prasyarat atau langkah umum, pertimbangkan untuk memisahkannya. Anda dapat menggunakan setup_test atau parameterisasi untuk meminimalkan jumlah kode berulang.
Mengikuti pendekatan ini akan membuat pengujian lebih mudah dibaca dan di-debug karena menunjukkan dengan jelas langkah dan kondisi mana yang gagal.
Contoh
test_verify_process():
device.start_process()
# precondition 1
device.send_signal1()
# verification signal1 received
...
# precondition 2
device.send_signal2()
# verification signal2 received
...
# precondition 3
device.start_agent()
# verification behavior
...
device.kill_process()
test_setup_test():
super().setup_test()
device.start_process()
test_signal1():
# precondition
device.send_signal1()
# verification signal1 received
...
test_signal2():
# precondition
device.send_signal2()
# verification signal2 received
...
test_agent():
# precondition
device.start_agent()
# verification behavior
...
teardown_test():
device.kill_process()
super().teardown_test()
Perilaku pengujian deterministik
Hindari menambahkan kondisional dalam pengujian yang mencabangkan perilakunya. Jika verifikasi perlu dibagi, gunakan dua kasus pengujian yang berbeda.
Jangan gunakan pengecualian
Pengujian dan helper umum harus menggunakan pernyataan, bukan pengecualian. Hal ini memfasilitasi proses debug dan mengikuti pola pengujian.
Contoh
result = self.some_calculations()
if result is None:
raise Exception("No result")
result = self.some_calculations()
self.get_test_validator().assert_is_not_none(result)
Contoh
if not self.device.is_subprocess_running(
self.EXPECTED_PROCESS
):
raise Exception("Process is not running")
self.get_test_validator().assert_true(
self.device.is_subprocess_running(self.EXPECTED_PROCESS),
"Process is not running"
)
Jangan gunakan sleep
Hindari penggunaan sleep karena dapat meningkatkan waktu eksekusi uji dan menyebabkan ketidakstabilan.
Jika pengujian mengharuskan menunggu peristiwa atau verifikasi untuk dilanjutkan, gunakan Metode Menunggu yang disediakan dalam framework.
Gunakan metode menunggu dengan hati-hati karena eksekusi uji akan tetap diblokir hingga kondisi cocok atau waktu tunggu tercapai.
Jika Anda perlu menunggu kondisi selesai dalam pengujian, ajukan pertanyaan berikut:
Berapa waktu tunggu yang wajar?
Jika peristiwa diharapkan terjadi dalam jangka waktu tertentu, waktu tunggu harus sesuai dengan ekspektasi tersebut untuk memastikan pengujian gagal dengan cepat. Kurangi waktu tunggu jika perlu (default-nya adalah 30 detik).
Seberapa mahal operasi yang dilakukan oleh metode menunggu?
Hindari sering memanggil operasi yang mahal. Tingkatkan interval polling jika perlu (default-nya adalah 0,5 detik).
Kasus pengujian dengan persyaratan
Jika pengujian memiliki kasus pengujian dengan persyaratan eksplisit untuk berfungsi (misalnya, target tempat pengujian harus dijalankan), Anda dapat melewatinya jika tidak memenuhi persyaratan:
def test_with_requirement():
self.get_test_validator().skip_if(expr, reason)
# Test case