Yunit 6 / 11

Unit Test Generation at Testability: Matatag na Pagsubok gamit ang AI

Mga nadagdag:

  • Kakayahang pigilan ang artificial intelligence mula sa pagtanggap ng maling gawi bilang 'tama' sa pamamagitan ng pagkalkula ng inaasahang halaga sa mga unit test nang hiwalay sa tuntunin sa pagtanggap
  • Kakayahang mag-print ng mabilis, independyente at paulit-ulit na mga pagsubok sa pamamagitan ng paglalapat ng AAA at FIRST na mga prinsipyo at panunuya ng mga panlabas na dependency
  • Kakayahang subukan ang mga pagsubok na may mutation (pagsira ng code) at kilalanin ang mahirap na pagsubok na code bilang amoy ng disenyo

Ang pinakamalaki at pinakamabilis na layer ng testing pyramid ay unit testing — pagsubok na nagbe-verify ng isang function o maliit na piraso ng code na nakahiwalay sa lahat ng iba pa. Ang libu-libong mga unit test ay tumatakbo sa loob ng ilang segundo at nakakuha ng bug habang ang code ay nasa screen ng developer. Ang artificial intelligence (AI) ay marahil ang pinaka-mahusay sa paggawa ng mga unit test: binibigyan mo ito ng function, ang AI ay gumagawa ng dose-dosenang mga pagsubok. Ngunit ang mismong kaginhawaan na ito ay nagbubunga ng pinakamalaking bitag: Ang AI ay madaling gumagawa ng mga pagsubok na "maliwanag na berde ngunit hindi nagpapatunay ng anuman" o tinatanggap ang kasalukuyang (marahil may mali) na gawi ng code bilang "tama". Sa unit na ito matututunan mo kung paano magsulat ng mga tunay na protective unit test gamit ang AI at ang kaugnayan sa pagitan ng masusubok na code at AI.

Mga katangian ng isang mahusay na pagsubok sa yunit: UNA

Ang magagandang unit test ay sumusunod sa UNANG mga prinsipyo: Mabilis, Independent (hindi dapat nakadepende sa isa't isa ang mga pagsusulit), Nauulit (nauulit — parehong resulta sa anumang kapaligiran), Self-validating (clear pass/fail), Napapanahon (sa oras). Paalalahanan ang iyong sarili ng mga prinsipyong ito kapag gumagawa ng mga pagsubok sa AI; partikular na hilingin na ang pagsubok ay hindi nakasalalay sa labas ng mundo (aktwal na database, network, orasan) upang maging "independiyente" at "nauulit".

AAA pattern at nagpapahayag na paninindigan

Ang isang solidong unit test ay sumusunod sa AAA structure: Ayusin (maghanda — mag-set up ng mga input at dependencies), Kumilos (execute — tawagan ang function sa ilalim ng pagsubok), Assert (validate — ihambing ang resulta sa inaasahang halaga). Ang kritikal ay igiit. Ang pinakakaraniwang pagkakamali na ginagawa ng AI ay ang pagkuha ng assert mula sa output ng code sa ilalim ng pagsubok - ang "anuman ang ibalik ng code ay totoo" na lohika. Ginagawa nitong walang kabuluhan ang pagsubok. Ang tamang paraan ay upang matukoy ang inaasahang halaga nang nakapag-iisa (mula sa pamantayan sa pagtanggap, kalkulahin ito nang manu-mano).

Pansin: Kung sasabihin mo sa AI "magsulat ng pagsubok para sa function na ito", maaaring patakbuhin ng AI ang function at isulat ang output nito bilang "inaasahan". Ang pagsubok na ito ay pumasa kahit na ang function ay hindi totoo. Sa halip, sabihin ang "kinakalkula mo ang mga inaasahang resulta ayon sa mga patakarang ito, huwag i-reference ang kasalukuyang output ng function."

Mga kunwaring, stub at dependencies

Ang pagsubok sa unit ay nangangailangan ng paghihiwalay. Kung ang iyong function ay nakasalalay sa isang database o API, ang mga ito ay papalitan ng mga mock na bagay (mock/stub — isang kinokontrol, dummy na kapalit para sa tunay na dependency) sa pagsubok. Ginagawa nitong mabilis, independiyente at maaaring kopyahin ang pagsubok. Ang AI ay maaaring gumawa ng kunwaring pag-install; Ngunit mag-ingat sa labis na pangungutya: kung kinukutya mo ang lahat, ang pagsubok ay magpapatunay lamang ng "kung ano ang ibinabalik ng pangungutya", hindi ang aktwal na lohika. Balanse: tularan ang labas ng mundo, isagawa ang tunay na lohika sa ilalim ng pagsubok.

Testability at AI

Mayroong isang kawili-wiling feedback: ang code na mahirap subukan ay kadalasang hindi maganda ang disenyong code. Kung ang AI ay may problema sa pagsulat ng mga pagsubok sa isang function (napakaraming dependency, nakatagong pandaigdigang estado, mga side effect), iyon ay isang amoy ng disenyo. Ang pagtatanong sa AI "paano mo isasaalang-alang ang code na ito upang gawin itong masusubok" ay humahantong sa parehong mas mahusay na pagsubok at mas mahusay na code.

Mga naka-parameter na pagsubok at pagkakaiba-iba ng data

Ang pagsulat ng isang hiwalay na pagsubok sa bawat oras upang i-verify ang parehong panuntunan na may iba't ibang mga input ay parehong nakakapagod at mahirap panatilihin. Parameterized na pagsubok — isang istraktura na paulit-ulit na nagpapatakbo ng parehong lohika ng pagsubok sa isang listahan ng mga input at inaasahang resulta — inaalis ang pag-uulit na ito: ang isang katawan ng pagsubok ay pinapakain ng dose-dosenang mga pares ng input. Napakahusay ng AI sa paggawa ng mga talahanayan ng inaasahang resulta ng input na ito kapag ibinigay mo ang iyong mga panuntunan sa pagtanggap; Sa partikular, sistematikong itinatala nito ang mga halaga ng limitasyon at mga klase ng equivalence.

Ngunit mayroong isang bitag din dito: ang AI ay may posibilidad na makuha ang inaasahang resulta sa nabuong talahanayan mula sa code na sinusuri. Ang error na ito ay mas mapanganib sa parameterized na pagsubok, dahil ang isang solong maling logic ay nagpapawalang-bisa sa dose-dosenang mga linya. Samakatuwid, palaging kalkulahin nang hiwalay ang column ng inaasahang resulta ayon sa tuntunin sa pagtanggap at manu-manong patunayan ang hindi bababa sa ilang row. Humingi din ng column ng paglalarawan "ano ang kinakatawan ng bawat row"; kaya kapag naputol ang isang hilera, makikita mo kaagad kung aling estado ang nasira.

Tip: Sadyang magdagdag ng "trap row" sa naka-parameter na talahanayan ng pagsubok — ibig sabihin, sadyang mali ang pagkaka-type ng resulta. Kung hindi naging pula ang linyang iyon kapag pinatakbo mo ang pagsubok, hindi talaga bini-verify ng iyong pagsubok ang sitwasyong iyon. Ito ay isang mabilis na mock-pass check.

Mahinang prompt / Malakas na prompt

Mahina: "Sumulat ng unit test para sa function na ito."
Malakas: Sumulat ng [language/framework] na mga unit test para sa function na "taxCalculate(amount, rate). Acceptance rule: result = amount * rate, rounded to 2 decimals; negative amount or rate throws error; returns 0 if rate is 0. Gamitin ang AAA structure. Manu-manong kalkulahin ang mga inaasahang value ayon sa mga panuntunang ITO, huwag i-reference ang kasalukuyang round bound, negatibong mga kaso ng desimal. Hayaang ilarawan ng pangalan ng bawat pagsubok ang panuntunang bini-verify nito na "Hindi."

Napakahusay na prompt; Nagbibigay ito ng tuntunin sa pagtanggap, independiyenteng inaasahang halaga ng inaasahan, istraktura at mga edge na kaso. Kaya, ang pagsubok ay nagiging tagapag-alaga ng panuntunan, hindi ang salamin ng code.

talahanayan ng kalidad ng pagsubok ng unit

sintomas

Masamang pagsubok (pekeng tiwala)

magandang pagsubok

igiit

Wala o "hindi null"

Inaasahang kongkretong halaga

Inaasahang mapagkukunan ng halaga

Output ng function

Panuntunan sa pagtanggap / manu-manong pagkalkula

pagkagumon

Aktwal na DB/network/oras

Insulated na may mock/stub

kaso sa gilid

Tanging masayang daan

limitasyon, negatibo, pagkakamali

Kapag sinira mo ang code

nananatiling berde

nagiging pula

Pangalan

test1, testMethod

inilalarawan ang panuntunang pinatutunayan nito

Apat na maaaring kopyahin na mga template

1) Pagsubok ng unit na batay sa panuntunan:

Ang iyong tungkulin: senior software test engineer. Sumulat ng unit test sa sumusunod na function na may [language/framework]: [signature]. Acceptance rules: [rules].- Gumamit ng AAA structure.- Manu-manong kalkulahin ang mga inaasahang value ayon sa mga panuntunang ITO; HUWAG sumangguni sa kasalukuyang output ng function. - Takpan ang limitasyon, negatibo, error at masayang landas na may hiwalay na mga pagsubok. - Hayaang ilarawan ng bawat pangalan ng pagsubok ang panuntunang bini-verify nito. - Kutyain ang mga panlabas na dependencies; Gawing gumana ang aktwal na lohika.

2) Kontrol ng paglaban sa mutation:

Tingnan ang mga unit test na ito. Maglista ng 5 menor de edad na pag-aayos na maaari kong gawin sa code na nasa ilalim ng pagsubok (a - sa halip na isang +, a >= sa halip na isang >, isang boundary shift) at sabihin sa akin para sa bawat isa ALIN sa mga pagsubok na ito ang magiging pula? Kung walang ibinalik, hindi sapat ang pagsubok. Code + tests: [paste]

3) Pagsusuri sa pagiging masusubok:

Bakit mahirap magsulat ng unit test para sa function na ito? Hidden addiction, global status, side effects, marami bang responsibilidad? Magmungkahi ng kaunting refactoring upang gawin itong masusubok; huwag baguhin ang ugali. Code: [i-paste]

4) Hindi kumpletong pagkumpleto ng senaryo:

Ang sumusunod na function at magagamit na mga pagsubok ay ibinigay. Ilista kung aling gawi/edgecase ang HINDI pa nasubok (scope gap) at magdagdag ng pagsubok para sa bawat isa. Function+tests: [i-paste]

tatlong mini case

Kaso 1 — Subukan ang pag-mirror sa code. Ang isang developer ay nagkaroon ng AI na sumulat ng isang pagsubok para sa rounding function; 10 mga pagsubok ay berde. Sa katunayan, ang function ay umiikot sa maling direksyon, ngunit kinuha ng AI ang mga inaasahang halaga mula sa output ng function, kaya ang mga pagsubok ay itinuturing na ang error ay "totoo". Kapag ang mga inaasahang halaga ay manu-manong kinakalkula gamit ang "rule-driven" na template, 4 na pagsubok ang naging pula at ang tunay na error ay nahayag.

Case 2 — Ang halaga ng mutation control. Isang team ang umasa sa 45 unit tests. Sinubukan ang 20 menor de edad na pag-tweak sa code na may "pagsusuri ng katatagan ng mutation"; Ang mga pagsubok ay nakakuha lamang ng 11 sa kanila. Ang natitirang 9 na pagkagambala ay tahimik na lumipas. Pinalakas ng pangkat ang mahihinang pagsubok; Isang aktwal na error sa pagkalkula ang nakuha ng mga pinahusay na pagsubok na ito sa susunod na release.

Kaso 3 — Ang hindi mapatunayan ay isang amoy ng disenyo. Ang AI ay hindi makapagsulat ng mga pagsubok para sa isang function ng pag-order, palagi nitong kailangan ang totoong database. Ang template na "testability review" ay nagpakita na ang function ay naka-embed sa database access. Kapag inalis ang dependency injection, maaaring isulat ang mga pagsubok at naging mas malinis ang code.

Mga karaniwang pagkakamali

  • Pagkuha ng inaasahang halaga mula sa code. Tinatanggap ng AI ang output ng function bilang "tama"; pagsubok na nagpapatunay ng may sira na code.
  • Pagsubok nang walang paninindigan o may maliit na paninindigan. "Hindi siya naghagis ng error, pumasa siya" logic; Wala itong kinukumpirma.
  • Matinding pangungutya. Kinukutya ang lahat at sinusubukan lamang kung ano ang ibinabalik ng kutya; hindi nasusubok ang tunay na lohika.
  • Ang masayang daan lang. Pag-bypass sa limitasyon, negatibo at mga estado ng error.
  • Hindi pagsubok sa pamamagitan ng pagsira sa code. Nagtitiwala sa berde nang hindi sinusuri ang mutation.
  • Hindi pinapansin ang untestability. Hindi kinikilala at ayusin ang masamang disenyo sa halip na itulak ang mahirap na pagsubok.

Sa buod

Ang mga unit test ay ang pinakamabilis at pinakamalaking layer ng testing pyramid; Nahuhuli nito ang pagkakamali sa pinakamurang sandali. Napakahusay ng AI na gumawa ng mga unit test, ngunit ang pinakamalaking pitfall nito ay ang pagsusulat ng mga pagsubok na ipinapalagay na "tama" ang maling gawi sa pamamagitan ng pagkuha ng inaasahang halaga mula sa mismong code. Solusyon: ibigay ang mga tuntunin sa pagtanggap, manu-manong kalkulahin ang inaasahang mga halaga, ipatupad ang mga prinsipyo ng AAA at FIRST, kutyain ang labas ng mundo at patakbuhin ang aktwal na lohika, at subukan ang bawat pagsubok sa pamamagitan ng mutation (pagsira sa code). Ang code na mahirap subukan ay isang sign ng disenyo na kailangang ayusin.

Gawain ng aplikasyon

Pumili ng function na naglalaman ng panuntunan sa negosyo mula sa sarili mong proyekto. Sumulat ng mga panuntunan sa pagtanggap at ipasulat ang mga pagsubok sa AI gamit ang template na "rule-driven unit testing"; Ipakalkula nang manu-mano ang inaasahang mga halaga. Pagkatapos ay ilapat ang "pagsusuri ng katatagan ng mutation": gumawa ng hindi bababa sa 5 maliit na pahinga sa code at sukatin kung gaano karaming mga pagsubok ang nagiging pula. Magdagdag ng bagong pagsubok para sa hindi nahuhuling mga katiwalian. Iulat kung gaano karaming mga pagkagambala ang nahuli (tulad ng marka ng mutation).

checklist

  • [ ] Ibinigay ko ang mga panuntunan sa pagtanggap at manual na kinakalkula ang inaasahang mga halaga.
  • [ ] Tiniyak ko na ang mga pagsubok ay hindi nakukuha ang inaasahang halaga mula sa code.
  • [ ] Nagtatag ako ng independiyenteng pagsubok na sumusunod sa AAA at FIRST na mga alituntunin.
  • [ ] Tinuya ko ang mga panlabas na dependency at pinatakbo ang aktwal na lohika.
  • [ ] Sinaklaw ko ang limitasyon, negatibo at mga kaso ng error.
  • [ ] Sa pamamagitan ng paglabag sa code (mutation) napatunayan ko na talagang nagpoprotekta ang mga pagsubok.