Sistem testleri, SDV Test Çerçevesi kullanılarak oluşturulan tüm SDV testlerini ifade eder.
Test oluşturma
Test konumu
<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
Dosyaları test etme
README.md: Tüm testler, testin amacının ve nasıl çalıştırılacağının açıklamasını içermelidir.Test dosyası: Tüm testler benzer bir yapıya sahiptir:
"""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()
- Derleme dosyası:
Android.bp. Dosya yapısı aşağıdaki gibidir:
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>",
}
Adlandırma kuralı
Farklı test türlerini tanımlamak ve bulmak için testler belirli bir adlandırma kuralına göre oluşturulmalıdır:
- Örnek test:
- Dosya adı:
sdv_sample_<NAME>_test.py - Sınıf adı:
SdvSampleNameTest
- Dosya adı:
- Uçtan uca test:
- Dosya adı:
sdv_e2e_<NAME>_test.py - Sınıf adı:
SdvE2ENameTest
- Dosya adı:
- Uzun süreli test:
- Dosya adı:
sdv_long_running_<NAME>_test.py - Sınıf adı:
SdvLongRunningNameTest
- Dosya adı:
- Performans testi:
- Dosya adı:
sdv_performance_<NAME>_test.py - Sınıf adı:
SdvPerformanceNameTest
- Dosya adı:
- Donanım testi:
- Dosya adı:
sdv_hw_<NAME>_test.py - Sınıf adı:
SdvHWNameTest
- Dosya adı:
Kod kuralları
Bu bölümde, SDV sistem testleri yazmayla ilgili yönergeler ve en iyi uygulamalar yer almaktadır.
Python ve Mobly
Python stil kılavuzu ve Mobly ile ilgili en iyi uygulamalar hakkında bilgi edinin ve SDV'ye özel aşağıdaki önerileri göz önünde bulundurun:
Onaylar dışında Mobly içe aktarma işlemlerini doğrudan kullanmaktan kaçının. SDV Test Çerçevesi, SDV'ye odaklanarak bu çerçeveyi temel alır.
Onaylar: Mobly onaylarını doğrudan kullanın.
SDV testleri
Aşağıdaki bölümlerde, SDV Test Çerçevesi'nde test geliştirme ile ilgili özel yönergeler ve en iyi uygulamalar açıklanmaktadır.
Kurulum ve temizleme
Kurulum ve temizleme kodu, test durumlarının dışında olmalıdır. Test başarısız olsa bile cihazın düzgün bir şekilde temizlenmesi için kaldırma yöntemleri çağrılır.
Kurulum ve sökme kodunun konumu, test kesintiye uğrasa bile testin özel ihtiyaçlarına bağlıdır:
- Yalnızca testin başında ve sonunda bir kez çalıştırmak için
setup_classveteardown_classkullanın. Örneğin, cihazları alma, değişken değerlerini veya test durumları arasında değişmeyen durumu ayarlama, ortak cihaz özelliklerini yapılandırma ya da işaretleri ayarlama.
def setup_class(self):
super().setup_class()
# setup code
def teardown_class(self):
# teardown code
super().teardown_class()
- Test durumları arasında, her birinden önce ve sonra çalıştırılır. Örneğin, etkileşimli oturum veya ortak hizmet yürütme.
def setup_test(self):
super().setup_test()
# setup code
def teardown_test(self):
# teardown code
super().teardown_test()
Parametreli test durumları
Kod tekrarını önlemek için adımlar farklı test durumlarında ortak olduğunda parametreleştirilmiş test durumlarını kullanın.
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
Örnekte iki test durumu (test_name_ab ve test_name_cd) oluşturulur.
Davranış doğrulaması için bir test durumu
Test durumları kısa olmalı ve belirli bir davranışa odaklanmalıdır. Birden fazla davranış ortak ön koşulları veya adımları paylaşıyorsa bunları bölmeyi düşünün. Tekrarlanan kod miktarını en aza indirmek için setup_test veya parametreleştirmeyi kullanabilirsiniz.
Bu yaklaşımı izlemek, hangi adımların ve koşulların başarısız olduğunu açıkça gösterdiği için testlerin okunmasını ve hata ayıklamasını kolaylaştırır.
Örnek
def test_verify_process(self):
self.device.start_process()
# precondition 1
self.device.send_signal1()
# verification signal1 received
...
# precondition 2
self.device.send_signal2()
# verification signal2 received
...
# precondition 3
self.device.start_agent()
# verification behavior
...
self.device.kill_process()
def setup_test(self):
super().setup_test()
self.device.start_process()
def test_signal1(self):
# precondition
self.device.send_signal1()
# verification signal1 received
...
def test_signal2(self):
# precondition
self.device.send_signal2()
# verification signal2 received
...
def test_agent(self):
# precondition
self.device.start_agent()
# verification behavior
...
def teardown_test(self):
self.device.kill_process()
super().teardown_test()
Deterministik test davranışı
Teste, davranışını dallara ayıran koşullar eklemekten kaçının. Bir doğrulamanın bölünmesi gerekiyorsa bunun yerine iki farklı test durumu kullanın.
İstisnaları kullanmama
Testler ve yaygın yardımcılar, istisnalar yerine onaylamaları kullanmalıdır. Bu, hata ayıklamayı kolaylaştırır ve test kalıplarına uyar.
Örnek
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)
Örnek
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"
)
Uyku modunu kullanma
Test işlemi süresini artırdığı ve tutarsızlığa neden olduğu için sleep kullanmaktan kaçının.
Testin devam etmesi için bir etkinliğin veya doğrulamanın beklenmesi gerektiğinde çerçevede sağlanan bekleme yöntemlerini kullanın.
Test işlemi, koşul karşılanana veya zaman aşımı süresi dolana kadar engellenmiş olarak kalacağından bekleme yöntemlerini dikkatli kullanın.
Bir testte bir koşulun tamamlanmasını beklemeniz gerektiğinde aşağıdaki soruları sorun:
Makul bir zaman aşımı süresi ne kadardır?
Bir etkinliğin belirli bir zaman aralığında gerçekleşmesi bekleniyorsa testin hızlı bir şekilde başarısız olması için zaman aşımı bu beklentiyle eşleşmelidir. Gerekirse zaman aşımı süresini azaltın (varsayılan değer 30 saniyedir).
Bekleme yönteminin gerçekleştirdiği işlem ne kadar maliyetli?
Yüksek maliyetli işlemleri sık sık çağırmaktan kaçının. Gerekirse yoklama aralığını artırın (varsayılan değer 0,5 saniyedir).
Gereksinimleri olan test durumları
Bir testte, çalışması için açık şartları olan test durumları varsa (örneğin, çalışması gereken hedef) şartları karşılamayan test durumlarını atlayabilirsiniz:
def test_with_requirement(self):
self.get_test_validator().skip_if(expr, reason)
# Test case