Pythonning Hypothesis kutubxonasi bilan xossaga asoslangan testlashni kashf eting. Chekka holatlarni topish va yanada mustahkam, ishonchli dasturiy ta'minotni yaratish uchun misolga asoslangan testlardan uzoqlashing.
Birlik Testlaridan Tashqarida: Pythonning Hypothesis kutubxonasi bilan xossaga asoslangan testlashga chuqur sho'ng'ish
Dasturiy ta'minotni ishlab chiqish dunyosida sinovdan o'tkazish sifatning asosidir. O'nlab yillar davomida ustunlik qiluvchi paradigma misolga asoslangan testlash bo'lgan. Biz ehtiyotkorlik bilan kirishlarni yaratamiz, kutilgan natijalarni aniqlaymiz va kodimiz rejalashtirilganidek ishlashini tasdiqlash uchun tekshiruvlarni yozamiz. unittest
va pytest
kabi freymvorklarda topilgan bu yondashuv kuchli va muhimdir. Lekin sizga hatto o'ylab ko'rmagan xatolarni topishingiz mumkin bo'lgan qo'shimcha yondashuv haqida aytsam-chi?
Xossaga asoslangan testlash dunyosiga xush kelibsiz, bu paradigma ma'lum misollarni sinovdan o'tkazishdan ko'ra, kodingizning umumiy xossalarini tasdiqlashga yo'naltiriladi. Va Python ekotizimida, bu yondashuvning ajitatsiz chempioni Hypothesis deb nomlangan kutubxonadir.
Ushbu keng qamrovli qo'llanma sizni Hypothesis bilan xossaga asoslangan testlashning to'liq boshlovchisidan ishonchli amaliyotchisiga olib boradi. Biz asosiy tushunchalarni o'rganamiz, amaliy misollarga kiramiz va yanada mustahkam, ishonchli va xatolarga chidamli dasturiy ta'minotni yaratish uchun ushbu kuchli vositani kundalik ishlab chiqish ish jarayoniga integratsiya qilishni o'rganamiz.
Xossaga Asoslangan Testlash Nima? Qarashning O'zgarishi
Hypothesisni tushunish uchun, avvalo, xossaga asoslangan testlashning asosiy g'oyasini tushunishimiz kerak. Keling, uni hammamiz bilgan an'anaviy misolga asoslangan testlash bilan solishtiramiz.
Misolga Asoslangan Testlash: Tanishing Yo'l
Tasavvur qiling, siz my_sort()
nomli maxsus saralash funksiyasini yozgansiz. Misolga asoslangan testlash bilan sizning fikrlash jarayoningiz quyidagicha bo'ladi:
- "Oddiy, tartiblangan ro'yxat bilan sinab ko'raylik." ->
assert my_sort([1, 2, 3]) == [1, 2, 3]
- "Teskari tartiblangan ro'yxat haqida nima deyish mumkin?" ->
assert my_sort([3, 2, 1]) == [1, 2, 3]
- "Bo'sh ro'yxat haqida nima deyish mumkin?" ->
assert my_sort([]) == []
- "Takrorlanuvchi elementlarli ro'yxat?" ->
assert my_sort([5, 1, 5, 2]) == [1, 2, 5, 5]
- "Va manfiy sonlarli ro'yxat?" ->
assert my_sort([-1, -5, 0]) == [-5, -1, 0]
Bu samarali, lekin uning asosiy cheklovi bor: siz faqat o'zingiz o'ylagan holatlarni sinovdan o'tkazasiz. Sizning testlaringiz faqat sizning tasavvuringiz yaxshi bo'lsa yaxshi bo'ladi. Siz juda katta sonlar, suzuvchi nuqtali noaniqliklar, maxsus unicode belgilari yoki kutilmagan xatti-harakatlarga olib keladigan ma'lumotlarning murakkab kombinatsiyalari bilan bog'liq chekka holatlarni o'tkazib yuborishingiz mumkin.
Xossaga Asoslangan Testlash: Invariantlar haqida O'ylash
Xossaga asoslangan testlash skriptni ag'daradi. Ma'lum misollarni taqdim etish o'rniga, siz funksiyangizning xossalarini yoki invariantlarini aniqlaysiz - bu har qanday to'g'ri kirish uchun amal qilishi kerak bo'lgan qoidalar. Bizning my_sort()
funksiyamiz uchun bu xossalar quyidagilar bo'lishi mumkin:
- Natija tartiblangan: Har qanday sonlar ro'yxati uchun, chiqish ro'yxatidagi har bir element undan keyingisiga teng yoki undan kichik bo'ladi.
- Natija kirish bilan bir xil elementlarni o'z ichiga oladi: Saralangan ro'yxat asl ro'yxatning faqat bir permutatsiyasidir; hech qanday elementlar qo'shilmaydi yoki yo'qolmaydi.
- Funksiya idempotent: Agar allaqachon tartiblangan ro'yxatni saralash uni o'zgartirmasligi kerak. Ya'ni,
my_sort(my_sort(some_list)) == my_sort(some_list)
.
Bu yondashuv bilan siz test ma'lumotlarini yozmaysiz. Siz qoidalarni yozasiz. Keyin siz Hypothesis kabi freymvorkga xossalaringizni isbotlash uchun yuzlab yoki minglab tasodifiy, turli xil va ko'pincha ayyorona kirishlarni yaratishga imkon berasiz. Agar u xossani buzadigan kirish topsa, u xatoni topgan bo'ladi.
Hypothesis bilan Tanishing: Sizning Avtomatlashtirilgan Test Ma'lumotlari Generatoringiz
Hypothesis Python uchun eng yaxshi xossaga asoslangan testlash kutubxonasidir. U siz aniqlagan xossalarni oladi va ularga qarshi turish uchun test ma'lumotlarini yaratishning qiyin ishini bajaradi. Bu shunchaki tasodifiy ma'lumotlar generatori emas; bu xatolarni samarali topish uchun mo'ljallangan aqlli va kuchli vositadir.
Hypothesisning Asosiy Xususiyatlari
- Avtomatik Test Holatlarini Yaratish: Sizga kerak bo'lgan ma'lumotlarning shaklini aniqlaysiz (masalan, "butun sonlar ro'yxati", "faqat harflardan iborat satr", "kelajakdagi datetime"), va Hypothesis ushbu shaklga mos keladigan turli xil misollarni yaratadi.
- Intellektual Qisqartirish: Bu sehrli xususiyatdir. Agar Hypothesis muvaffaqiyatsiz test holatini topsa (masalan, sizning saralash funksiyangizni buzadigan 50 ta murakkab sonlar ro'yxati), u shunchaki ulkan ro'yxatni hisobot qilmaydi. U muvaffaqiyatsizlikni keltirib chiqaradigan eng kichik mumkin bo'lgan misolni topish uchun avtomatik ravishda va aqlli ravishda kirishni soddalashtiradi. 50 elementli ro'yxat o'rniga, u shunchaki
[inf, nan]
bilan muvaffaqiyatsizlik yuz berishini xabar qilishi mumkin. Bu disk raskadrovkani juda tez va samarali qiladi. - Silliq Integratsiya: Hypothesis
pytest
vaunittest
kabi mashhur test freymvorklari bilan mukammal integratsiya qilinadi. Ish oqimini o'zgartirmasdan mavjud misolga asoslangan testlaringiz yoniga xossaga asoslangan testlarni qo'shishingiz mumkin. - Strategiyalarning Boy Kutubxonasi: U oddiy butun sonlar va satrlardan tortib, murakkab, ichki ma'lumotlar tuzilmalarigacha, vaqt zonasi xabardor datetimelar va hatto NumPy massivlarigacha hamma narsani yaratish uchun o'rnatilgan "strategiyalarning" katta to'plami bilan birga keladi.
- Davlatli Testlash: Murakkab tizimlar uchun Hypothesis davlat o'tishlaridagi xatolarni topish uchun harakatlar ketma-ketligini sinovdan o'tkaza oladi, bu misolga asoslangan testlash bilan an'anaviy ravishda qiyin bo'lgan narsadir.
Boshlash: Sizning Birinchi Hypothesis Testingiz
Qo'limizni kir qilib olaylik. Hypothesisni tushunishning eng yaxshi yo'li uni amalda ko'rishdir.
O'rnatish
Birinchidan, siz Hypothesis va siz tanlagan test ishchi dasturini o'rnatishingiz kerak (biz pytest
dan foydalanamiz). Bu shunchalik oddiy:
pip install pytest hypothesis
Oddiy Misol: Mutlaq Qiymat Funksiyasi
Keling, bir sonning mutlaq qiymatini hisoblashga mo'ljallangan oddiy funksiyani ko'rib chiqaylik. Biroz xatoli amalga oshirilishi quyidagicha bo'lishi mumkin:
# my_math.py faylida def custom_abs(x): """Mutlaq qiymat funksiyasining maxsus amalga oshirilishi.""" if x < 0: return -x return x
Endi, keling test faylini, test_my_math.py
ni yozaylik. Birinchidan, an'anaviy pytest
yondashuvi:
# test_my_math.py (Misolga asoslangan) def test_abs_positive(): assert custom_abs(5) == 5 def test_abs_negative(): assert custom_abs(-5) == 5 def test_abs_zero(): assert custom_abs(0) == 0
Bu testlar o'tadi. Ushbu misollar asosida funksiyamiz to'g'ri ko'rinadi. Lekin endi, keling Hypothesis bilan xossaga asoslangan test yozaylik. Mutlaq qiymat funksiyasining asosiy xossasi nima? Natija hech qachon manfiy bo'lmasligi kerak.
# test_my_math.py (Hypothesis bilan xossaga asoslangan) from hypothesis import given from hypothesis import strategies as st from my_math import custom_abs @given(st.integers()) def test_abs_property_is_non_negative(x): """Xossa: Har qanday butun sonning mutlaq qiymati har doim >= 0.""" assert custom_abs(x) >= 0
Keling, buni tahlil qilaylik:
from hypothesis import given, strategies as st
: Biz kerakli komponentlarni import qilamiz.given
oddiy test funksiyasini xossaga asoslangan testga aylantiradigan dekoratordir.strategies
bizning ma'lumot generatorlarimizni topadigan moduldir.@given(st.integers())
: Bu testning asosidir.@given
dekoratori Hypothesisga ushbu test funksiyasini bir necha bor ishga tushirishni aytadi. Har bir ishga tushirish uchun, u berilgan strategiya,st.integers()
yordamida qiymat yaratadi va uni bizning test funksiyamizgax
argumenti sifatida uzatadi.assert custom_abs(x) >= 0
: Bu bizning xossamiz. Hypothesis qandaydir butun sonnix
tasavvur qilsa ham, funksiyamiz natijasi nolga teng yoki undan katta bo'lishi kerakligini tasdiqlaymiz.
Siz buni pytest
bilan ishga tushirganingizda, u ko'plab qiymatlar uchun o'tishi mumkin. Hypothesis 0, -1, 1, katta musbat sonlar, katta manfiy sonlar va boshqalarni sinab ko'radi. Bizning oddiy funksiyamiz bularning barchasini to'g'ri boshqaradi. Endi, keling, zaiflikni topish uchun boshqa strategiyani sinab ko'raylik.
# suzuvchi nuqtali sonlar bilan sinab ko'raylik @given(st.floats()) def test_abs_floats_property(x): assert custom_abs(x) >= 0
Agar siz buni ishga tushirsangiz, Hypothesis tezda muvaffaqiyatsiz holatni topadi!
Falsifying example: test_abs_floats_property(x=nan) ... assert custom_abs(nan) >= 0 AssertionError: assert nan >= 0
Hypothesis bizning funksiyamiz float('nan')
(Son emas) berilganda nan
natijasini qaytarishini aniqladi. nan >= 0
tekshiruvi noto'g'ri. Biz endi qo'lda sinab ko'rishga hech qachon o'ylamasligimiz mumkin bo'lgan nozik xatoni topdik. Biz ushbu holatni boshqarish uchun funksiyamizni tuzatishimiz mumkin, masalan, ValueError
chiqarish yoki ma'lum bir qiymatni qaytarish orqali.
Yana ham yaxshi, agar xatolik juda aniq suzuvchi nuqtali son bilan bog'liq bo'lsa-chi? Hypothesisning qisqartiruvchisi muvaffaqiyatsiz tushgan katta, murakkab sonni olib, hali ham xatolikka olib keladigan eng sodda versiyasiga qisqartirgan bo'lardi.
Strategiyalarning kuchi: Test ma'lumotlaringizni yaratish
Strategiyalar Hypothesisning yuragi hisoblanadi. Ular ma'lumotlarni yaratish uchun retseptlardir. Kutubxona ko'plab o'rnatilgan strategiyalarni o'z ichiga oladi va siz tasavvur qilishingiz mumkin bo'lgan deyarli har qanday ma'lumotlar tuzilmasini yaratish uchun ularni birlashtirishingiz va sozashingiz mumkin.
Umumiy O'rnatilgan Strategiyalar
- Raqamli:
st.integers(min_value=0, max_value=1000)
: Butun sonlarni yaratadi, ixtiyoriy ravishda ma'lum bir diapazon ichida.st.floats(min_value=0.0, max_value=1.0, allow_nan=False, allow_infinity=False)
: Maxsus qiymatlar ustidan nozik nazorat bilan suzuvchi nuqtali sonlarni yaratadi.st.fractions()
,st.decimals()
- Matn:
st.text(min_size=1, max_size=50)
: Ma'lum bir uzunlikdagi unicode satrlarini yaratadi.st.text(alphabet='abcdef0123456789')
: Maxsus belgi to'plamidan (masalan, geteks kodlari uchun) satrlarni yaratadi.st.characters()
: Individual belgilarni yaratadi.
- Kolleksiyalar:
st.lists(st.integers(), min_size=1)
: Har bir elementi butun son bo'lgan ro'yxatlarni yaratadi. Bu yerda biz boshqa strategiyani argument sifatida uzatayotganimizga e'tibor bering! Buni kompozitsiya deb atashadi.st.tuples(st.text(), st.booleans())
: Ma'lum bir tuzilishga ega bo'lgan katakchalarni yaratadi.st.sets(st.integers())
st.dictionaries(keys=st.text(), values=st.integers())
: Belgilangan kalit va qiymat turlari bilan lug'atlarni yaratadi.
- Vaqtli:
st.dates()
,st.times()
,st.datetimes()
,st.timedeltas()
. Bular vaqt zonasi xabardor qilinishi mumkin.
- Boshqa:
st.booleans()
:True
yokiFalse
yaratadi.st.just('constant_value')
: Har doim bitta doimiy qiymatni yaratadi. Murakkab strategiyalarni yaratish uchun foydali.st.one_of(st.integers(), st.text())
: Berilgan strategiyalardan biridan qiymat yaratadi.st.none()
: FaqatNone
yaratadi.
Strategiyalarni Birlashtirish va Transformatsiya qilish
Hypothesisning haqiqiy kuchi uning soddaroq strategiyalardan murakkab strategiyalarni yaratish qobiliyatidan kelib chiqadi.
.map()
dan Foydalanish
.map()
metodi bir strategiyadan qiymatni olib, uni boshqa narsaga aylantirishga imkon beradi. Bu sizning maxsus sinflaringiz obyektlarini yaratish uchun juda mos keladi.
# Oddiy ma'lumotlar sinfi from dataclasses import dataclass @dataclass class User: user_id: int username: str # User obyektlarini yaratish uchun strategiya user_strategy = st.builds( User, user_id=st.integers(min_value=1), username=st.text(min_size=3, alphabet='abcdefghijklmnopqrstuvwxyz') ) @given(user=user_strategy) def test_user_creation(user): assert isinstance(user, User) assert user.user_id > 0 assert user.username.isalpha()
.filter()
va assume()
dan Foydalanish
Ba'zan siz yaratilgan ma'lumotlarni rad etishingiz kerak bo'ladi. Masalan, sizning summasi nol bo'lmagan butun sonlar ro'yxati kerak bo'lishi mumkin. Siz .filter()
dan foydalanishingiz mumkin:
st.lists(st.integers()).filter(lambda x: sum(x) != 0)
Biroq, .filter()
dan foydalanish samarasiz bo'lishi mumkin. Agar shart tez-tez noto'g'ri bo'lsa, Hypothesis to'g'ri misolni yaratish uchun uzoq vaqt sarflashi mumkin. Ko'pincha assume()
dan foydalanish yaxshiroq yondashuvdir:
from hypothesis import assume @given(st.lists(st.integers())) def test_something_with_non_zero_sum_list(numbers): assume(sum(numbers) != 0) # ... sizning test mantiqiyiz shu yerda ...
assume()
Hypothesisga aytadi: "Agar bu shart bajarilmasa, bu misolni tashlab, yangisini sinab ko'ring." Bu test ma'lumotlarini cheklashning yanada to'g'ridan-to'g'ri va ko'pincha samarali usuli.
st.composite()
dan Foydalanish
Bir yaratilgan qiymat boshqasiga bog'liq bo'lgan haqiqatan ham murakkab ma'lumotlar yaratish uchun st.composite()
kerakli vositadir. U sizga draw
deb nomlangan maxsus funksiyani argument sifatida oladigan funksiyani yozishga imkon beradi, uni bosqichma-bosqich boshqa strategiyalardan qiymatlarni tortib olish uchun ishlatishingiz mumkin.
Klassik misol - bu ro'yxat va shu ro'yxatga to'g'ri keladigan indeksni yaratish.
@st.composite def list_and_index(draw): # Birinchidan, bo'sh bo'lmagan ro'yxatni tortib oling my_list = draw(st.lists(st.integers(), min_size=1)) # Keyin, shu ro'yxat uchun to'g'ri kelishi kafolatlangan indekni tortib oling index = draw(st.integers(min_value=0, max_value=len(my_list) - 1)) return (my_list, index) @given(data=list_and_index()) def test_list_access(data): my_list, index = data # Ushbu kirish strategiyani qanday yaratganimiz sababli xavfsiz bo'lishi kafolatlangan element = my_list[index] assert element is not None # Oddiy tekshiruv
Hypothesis Amalda: Haqiqiy Dunyo Ssenariylari
Keling, ushbu tushunchalarni dasturiy ta'minot ishlab chiquvchilari har kuni duch keladigan yanada real muammolarga qo'llaylik.
Ssenariy 1: Ma'lumotlarni Serializatsiya qilish Funksiyasini Testlash
Tasavvur qiling, foydalanuvchi profilini (lug'at) URL-xavfsiz satrga serializatsiya qiladigan va uni deserializatsiya qiladigan funksiya. Asosiy xossa - jarayon mukammal teskarisi bo'lishi kerak.
import json import base64 def serialize_profile(data: dict) -> str: """Lug'atni URL-xavfsiz base64 satriga serializatsiya qiladi.""" json_string = json.dumps(data) return base64.urlsafe_b64encode(json_string.encode('utf-8')).decode('utf-8') def deserialize_profile(encoded_str: str) -> dict: """Satrni lug'atga teskari deserializatsiya qiladi.""" json_string = base64.urlsafe_b64decode(encoded_str.encode('utf-8')).decode('utf-8') return json.loads(json_string) # Endi test uchun # Biz JSON-mos lug'atlarni yaratadigan strategiyaga muhtojmiz json_dictionaries = st.dictionaries( keys=st.text(), values=st.recursive(st.none() | st.booleans() | st.floats(allow_nan=False) | st.text(), lambda children: st.lists(children) | st.dictionaries(st.text(), children), max_leaves=10) ) @given(profile=json_dictionaries) def test_serialization_roundtrip(profile): """Xossa: Kodlangan profilni deserializatsiya qilish asl profilni qaytarishi kerak.""" encoded = serialize_profile(profile) decoded = deserialize_profile(encoded) assert profile == decoded
Bu bitta test funksiyalarimizni turli xil ma'lumotlar bilan siqib chiqaradi: bo'sh lug'atlar, ichki ro'yxatlarga ega bo'lgan lug'atlar, unicode belgilariga ega bo'lgan lug'atlar, g'alati kalitlarga ega bo'lgan lug'atlar va boshqalar. Bu qo'lda bir nechta misol yozishdan ancha to'liqroq.
Ssenariy 2: Saralash Algoritmini Testlash
Keling, saralash misolimizga qaytamiz. Avval aniqlagan xossalarni qanday sinab ko'rish mumkin.
from collections import Counter def my_buggy_sort(numbers): # Keling, nozik xatoni kiritamiz: u takrorlanuvchilarni tushirib qoldiradi return sorted(list(set(numbers))) @given(st.lists(st.integers())) def test_sorting_properties(numbers): sorted_list = my_buggy_sort(numbers) # Xossa 1: Natija tartiblangan for i in range(len(sorted_list) - 1): assert sorted_list[i] <= sorted_list[i+1] # Xossa 2: Elementlar bir xil (bu xatoni topadi) assert Counter(numbers) == Counter(sorted_list) # Xossa 3: Funksiya idempotent assert my_buggy_sort(sorted_list) == sorted_list
Siz ushbu testni ishga tushirganingizda, Hypothesis tezda Xossa 2 uchun muvaffaqiyatsiz misolni, masalan, numbers=[0, 0]
ni topadi. Bizning funksiyamiz [0]
ni qaytaradi va Counter([0, 0])
Counter([0])
ga teng emas. Qisqartiruvchi muvaffaqiyatsiz misolning iloji boricha sodda ekanligini ta'minlaydi, bu xatoning sababini darhol tushunarli qiladi.
Ssenariy 3: Davlatli Testlash
Vaqt o'tishi bilan o'zgarib turadigan ichki davlatga ega obyektlar uchun (masalan, ma'lumotlar bazasi ulanishi, xarid qilish savati yoki kesh), xatolarni topish juda qiyin bo'lishi mumkin. Muammoni keltirib chiqarish uchun ma'lum bir operatsiyalar ketma-ketligi talab qilinishi mumkin. Hypothesis aynan shu maqsad uchun RuleBasedStateMachine
ni taqdim etadi.
Misol uchun, xotiradagi kalit-qiymat do'koni uchun oddiy APIni tasavvur qiling:
class SimpleKeyValueStore: def __init__(self): self._data = {} def set(self, key, value): self._data[key] = value def get(self, key): return self._data.get(key) def delete(self, key): if key in self._data: del self._data[key] def size(self): return len(self._data)
Biz uning xulq-atvorini modellashtirishimiz va davlat mashinasi bilan sinab ko'rishimiz mumkin:
from hypothesis.stateful import RuleBasedStateMachine, rule, Bundle class KeyValueStoreMachine(RuleBasedStateMachine): def __init__(self): super().__init__() self.model = {} self.sut = SimpleKeyValueStore() # Bundle() qoidalari o'rtasida ma'lumotlarni uzatish uchun ishlatiladi keys = Bundle('keys') @rule(target=keys, key=st.text(), value=st.integers()) def set_key(self, key, value): self.model[key] = value self.sut.set(key, value) return key @rule(key=keys) def delete_key(self, key): del self.model[key] self.sut.delete(key) @rule(key=st.text()) def get_key(self, key): model_val = self.model.get(key) sut_val = self.sut.get(key) assert model_val == sut_val @rule() def check_size(self): assert len(self.model) == self.sut.size() # Testni ishga tushirish uchun, siz shunchaki mashinadan va unittest.TestCase dan meros qilib olasiz # Pytestda, siz shunchaki testni mashina sinfiga tayinlashingiz mumkin TestKeyValueStore = KeyValueStoreMachine.TestCase
Hypothesis endi set_key
, delete_key
, get_key
va check_size
operatsiyalarining tasodifiy ketma-ketliklarini ishga tushiradi, tekshiruvlardan birini buzadigan ketma-ketlikni topishga harakat qiladi. U o'chirilgan kalitni olish to'g'ri ishlaydimi, ko'plab set va delete operatsiyalaridan keyin o'lcham izchilmi va siz qo'lda sinab ko'rmaydigan ko'plab boshqa stsenariylarni tekshiradi.
Eng Yaxshi Amaliyotlar va Ilg'or Maslahatlar
- Misol Ma'lumotlar Bazasi: Hypothesis aqlli. Xatolikni topsa, u muvaffaqiyatsiz misolni mahalliy katalogda (
.hypothesis/
) saqlaydi. Keyingi safar testlarni ishga tushirganingizda, u ushbu muvaffaqiyatsiz misolni birinchi bo'lib qayta ijro etadi, bu xato hali ham mavjudligini darhol bildiradi. Uni tuzatganingizda, misol endi qayta ijro etilmaydi. - Test Ishini Nazorat Qilish
@settings
bilan: Siz@settings
dekoratoridan foydalanib, test ishining ko'plab jihatlarini nazorat qilishingiz mumkin. Siz misollar sonini ko'paytirishingiz, bitta misol qancha vaqt ishlashi mumkinligi (cheksiz tsikllarni ushlash uchun) va ba'zi xavfsizlik tekshiruvlarini o'chirib qo'yishingiz mumkin.@settings(max_examples=500, deadline=1000) # 500 misolni ishga tushiring, 1-soniyali muddat @given(...) ...
- Muvaffaqiyatsizliklarni Qayta Ishlab Chiqarish: Har bir Hypothesis ishga tushirilganda urug' qiymatini chiqaradi (masalan,
@reproduce_failure('version', 'seed')
). Agar CI server sizning mahalliy kompyuteringizda takrorlana olmaydigan xatoni topsa, siz ushbu dekoratordan berilgan urug' bilan foydalanib, Hypothesisni aynan shu misollar ketma-ketligini ishga tushirishga majburlashingiz mumkin. - CI/CD bilan Integratsiya: Hypothesis har qanday uzluksiz integratsiya quvuriga mukammal mos keladi. Mahsulotga etib kelishdan oldin noma'lum xatolarni topish qobiliyati uni qimmatli xavfsizlik tarmog'iga aylantiradi.
Aqliy O'zgarish: Xossalar Haqida O'ylash
Hypothesisni qabul qilish shunchaki yangi kutubxonani o'rganishdan ko'proq narsani anglatadi; bu kodning to'g'riligi haqida yangicha fikrlashni qabul qilishdir. "Qanday kirishlarni sinab ko'rishim kerak?" deb o'ylash o'rniga, siz "Bu kod haqida universal haqiqatlar nimalardan iborat?" deb so'ray boshlaysiz.
Xossalarni aniqlashda sizga yordam beradigan savollar:
- Teskari operatsiya bormi? (masalan., serializatsiya/deserializatsiya, shifrlash/shifrdan chiqarish, siqish/siqishdan chiqarish). Xossa operatsiyani va uning teskarisini bajarish asl kirishni berishidir.
- Operatsiya idempotentmi? (masalan,
abs(abs(x)) == abs(x)
). Funksiyani bir martadan ortiq qo'llash bir marta qo'llash bilan bir xil natijani berishi kerak. - Bir xil natijani hisoblashning boshqa, soddaroq usuli bormi? Siz o'zingizning murakkab, optimallashtirilgan funksiyangizni oddiy, aniq to'g'ri versiya bilan bir xil natijani berishini tekshirishingiz mumkin (masalan, sizning g'arazli saralashingizni Pythonning o'rnatilgan
sorted()
funksiyasi bilan solishtirish). - Natija haqida har doim nima haq bo'lishi kerak? (masalan,
find_prime_factors
funksiyasining natijasi faqat tub sonlarni o'z ichiga olishi kerak va ularning mahsuloti kirishga teng bo'lishi kerak). - Davlat qanday o'zgaradi? (Davlatli testlash uchun) Har qanday to'g'ri operatsiyadan keyin qanday invariantlar saqlanishi kerak? (masalan, xarid qilish savatidagi buyumlar soni hech qachon manfiy bo'lishi mumkin emas).
Xulosa: Ishonchning Yangi Darajasi
Hypothesis bilan xossaga asoslangan testlash misolga asoslangan testlashni almashtirmaydi. Siz hali ham muhim biznes mantiqiy va yaxshi tushunilgan talablar uchun maxsus, qo'lda yozilgan testlarga muhtojsiz (masalan, "X mamlakatidan kelgan foydalanuvchi narx Y ni ko'rishi kerak").
Hypothesis taqdim etadigan narsa bu sizning kod xulq-atvorini o'rganish va kutilmagan chekka holatlarga qarshi himoya qilish uchun kuchli, avtomatlashtirilgan usuldir. U tinimsiz hamkor bo'lib ishlaydi, har qanday inson haqiqatda yozishi mumkin bo'lganidan ko'ra xilma-xil va ayyorona minglab testlarni yaratadi. Kodingizning asosiy xossalarini aniqlash orqali siz Hypothesis testlashi mumkin bo'lgan mustahkam spetsifikatsiyani yaratasiz, bu sizga dasturiy ta'minotingizga yangi darajadagi ishonchni beradi.
Keyingi safar funksiya yozganingizda, misollardan tashqariga o'ylashga bir daqiqa vaqt ajrating. O'zingizdan so'rang: "Qoidalar nimalardan iborat? Har doim nima haq bo'lishi kerak?" Keyin, ularni buzishga harakat qilishning qiyin ishini Hypothesisga topshiring. Nima topishiga hayron qolasiz va kodingiz bunga loyiq bo'ladi.