Vai meklējat veidu, kā vieglāk veikt testus? Mēs jums palīdzēsim! Skatiet šo rakstu un uzziniet, kā to izdarīt.
Mūsdienu lietojumprogrammu izstrādes pamatā ir viens vienkāršs noteikums:
Izmantojiet sastāvu
Mēs veidojam klases, funkcijas un pakalpojumus lielākos programmatūras blokos. Šis pēdējais elements ir pamats mikroservisi un sešstūra formas arhitektūra. Mēs vēlamies izmantot esošos risinājumus, integrēt tos ar mūsu programmatūru un uzreiz pāriet uz mūsu programmatūru. tirgus.
Vai vēlaties apstrādāt konta reģistrāciju un saglabāt lietotāja dati? Varat izvēlēties kādu no OAuth pakalpojumiem. Varbūt jūsu lietojumprogramma piedāvā kādu abonēšanu vai maksājumu? Ir daudzi pakalpojumi, kas var palīdzēt to apstrādāt. Vai jums ir nepieciešama tīmekļa vietnes analīze, bet nesaprotat, kā to darīt? GDPR? Droši izvēlieties kādu no gatavajiem risinājumiem.
Tas, kas no biznesa viedokļa padara izstrādi tik vienkāršu, var sagādāt galvassāpes - brīdī, kad nepieciešams uzrakstīt vienkāršu testu.
Fantastiskie zvēri: rindas, datubāzes un to testēšana
Vienības testēšana ir diezgan vienkārša. Ja jūs ievērojat tikai šos noteikumus, tad jūsu testēšanas vide un kods ir veselīgi. Kādi ir šie noteikumi?
Viegli rakstīt - vienības testu vajadzētu būt viegli uzrakstīt, jo jūs rakstāt daudz testu. Mazāk pūļu nozīmē, ka tiek uzrakstīts vairāk testu.
Lasāms - testa kodam jābūt viegli lasāmam. Tests ir stāsts. Tas apraksta programmatūras uzvedību, un to var izmantot kā dokumentācijas saīsinājumu. Labs vienības tests palīdz novērst kļūdas bez koda atkļūdošanas.
Uzticams - testam jābūt neveiksmīgam tikai tad, ja testējamā sistēmā ir kļūda. Acīmredzami? Ne vienmēr. Dažreiz testi ir veiksmīgi, ja tos izpilda pa vienam, bet neizdodas, ja tos izpilda kā kopumu. Tie ir veiksmīgi jūsu datorā, bet neizdodas CI (Darbojas manā datorā). Labam vienības testam ir tikai viens neveiksmes iemesls.
Fast - testiem jābūt ātriem. Sagatavošanai, palaišanai, palaišanai un pašai testu izpildei jābūt ļoti ātrai. Pretējā gadījumā jūs tos uzrakstīsiet, bet neizpildīsiet. Lēni testi nozīmē zaudētu uzmanību. Jūs gaidāt un skatāties uz progresa joslu.
Neatkarīga - visbeidzot, testam jābūt neatkarīgam. Šis noteikums izriet no iepriekšējiem. Tikai patiesi neatkarīgi testi var kļūt par vienību. Tie netraucē cits citam, tos var izpildīt jebkurā secībā, un iespējamās kļūdas nav atkarīgas no citu testu rezultātiem. Neatkarīgi nozīmē arī to, ka nav atkarīgi no ārējiem resursiem, piemēram, datu bāzēm, ziņojumapmaiņas pakalpojumiem vai failu sistēmas. Ja jums ir nepieciešama saziņa ar ārējiem resursiem, varat izmantot mocks, stubs vai dummy.
Viss kļūst sarežģīti, kad vēlamies uzrakstīt integrācijas testus. Tas nav slikti, ja vēlamies testēt vairākus pakalpojumus kopā. Taču, ja mums ir nepieciešams testēt pakalpojumus, kas izmanto ārējos resursus, piemēram, datubāzes vai ziņojumapmaiņas pakalpojumus, tad mēs sagādājam problēmas.
Lai palaistu testu, ir jāinstalē...
Pirms daudziem gadiem, kad mēs vēlējāmies veikt integrācijas testus un izmantot, piemēram, datubāzes, mums bija divas iespējas:
Datu bāzi varam instalēt lokāli. Iestatiet shēmu un izveidojiet savienojumu no mūsu testa;
Varam izveidot savienojumu ar esošo gadījumu "kaut kur kosmosā".
Abiem bija gan plusi, gan mīnusi. Taču abas ievieš papildu sarežģītības pakāpes. Dažreiz tā bija tehniska sarežģītība, ko radīja konkrētu rīku īpašības, piemēram, Oracle DB instalēšana un pārvaldība lokālajā hostī. Dažreiz tās bija neērtības procesā, piemēram, jums ir jāvienojas ar testu. komanda par JMS izmantošanu... katru reizi, kad vēlaties palaist testus.
Konteineri palīgā
Pēdējo 10 gadu laikā konteinerizācijas ideja ir guvusi atzinību nozarē. Tāpēc likumsakarīgs lēmums ir izvēlēties konteinerus kā risinājumu mūsu integrācijas testu problēmai. Tas ir vienkāršs un tīrs risinājums. Jūs vienkārši palaižat sava procesa izveidi, un viss darbojas! Jūs nevarat tam noticēt? Aplūkojiet šo vienkāršo maven kompilācijas konfigurāciju:
com.dkanejs.maven.plugins
docker-compose-maven-plugin
4.0.0
up
test-compile
up
${projekts.basedir}/docker-compose.yml
true
uz leju
pēc integrācijas testa
noslēgšanās
${project.basedir}/docker-compose.yml
true
Un docker-compose.yml fails arī izskatās diezgan jauki!
Iepriekš minētais piemērs ir ļoti vienkāršs. Tikai viena postgres datubāze, pgAdmin un viss. Kad palaižat
bash
$ mvn tīrs pārbaudīt
tad maven spraudnis iedarbina konteinerus un pēc testu veikšanas tos izslēdz. Problēmas sākas, kad projekts pieaug un pieaug arī mūsu compose fails. Katru reizi būs nepieciešams iedarbināt visus konteinerus, un tie būs dzīvi visas kompilācijas laikā. Situāciju var nedaudz uzlabot, mainot spraudņa izpildes konfigurāciju, taču ar to nepietiek. Sliktākajā gadījumā jūsu konteineri izsmeltu sistēmas resursus, pirms sākas testi!
Un tas nav vienīgais jautājums. Jūs nevarat palaist vienu integrācijas testu no savas IDE. Pirms tam konteineri ir jāpalaiž ar rokām. Turklāt nākamais maven palaidums nojauks šos konteinerus (skat. uz leju izpilde).
Tātad šis risinājums ir kā liels kravas kuģis. Ja viss darbojas labi, tad viss ir kārtībā. Jebkāda neparedzēta vai neparasta uzvedība noved pie tā, ka mums līdz kādai katastrofai.
Testēšanas konteineri - palaist konteinerus no testiem
Bet ko tad, ja mēs varētu palaist savus konteinerus no testiem? Šī ideja izskatās laba, un tā jau tiek īstenota. Testkonteineri, jo mēs runājam par šo projektu, šeit ir mūsu problēmu risinājums. Nav ideāls, bet neviens nav ideāls.
Tas ir Java bibliotēka, kas atbalsta JUnit un Spock testus, nodrošinot vieglus un vienkāršus veidus, kā palaist Docker konteiners. Aplūkosim to un uzrakstīsim kādu kodu!
Priekšnosacījumi un konfigurācija
Pirms sākam darbu, jāpārbauda konfigurācija. Testa konteineri nepieciešams:
Docker versijā v17.09,
Java minimālā versija 1.8,
Piekļuve tīklam, īpaši docker.hub.
Sīkāku informāciju par prasībām konkrētām OS un CI var atrast vietnē dokumentācija.
Tagad ir pienācis laiks pievienot dažas rindas uz pom.xml.
org.testcontainers
testcontainers-bom
${testcontaines.version}
pom
importēt
org.postgresql
postgresql
runtime
org.testcontainers
postgresql
test
org.testcontainers
junit-jupiter
test
Es izmantoju Testa konteineri versija 1.17.3, bet izmantojiet jaunāko.
Testi ar Postgres konteineru
Pirmais solis ir sagatavot konteinera gadījumu. To var izdarīt tieši testā, bet neatkarīga klase izskatās labāk.
public klase Postgres13TC extends PostgreSQLContainer {
private static final Postgres13TC TC = new Postgres13TC();
private Postgres13TC() {
super("postgres:13.2");
}
public static Postgres13TC getInstance() {
return TC;
}
@Override
public void start() {
super.start();
System.setProperty("DB_URL", TC.getJdbcUrl());
System.setProperty("DB_USERNAME", TC.getUsername());
System.setProperty("DB_PASSWORD", TC.getPassword());
}
@Override
public void stop() {
// neko nedara. Šī ir koplietojamā instance. Ļaujiet JVM apstrādāt šo operāciju.
}
}
Testu sākumā mēs izveidosim instance of Postgres13TC. Šajā klasē var apstrādāt informāciju par mūsu konteineru. Vissvarīgākās ir datu bāzes savienojuma virknes un akreditācijas dati. Tagad ir pienācis laiks uzrakstīt ļoti vienkāršu testu.
Es šeit izmantoju JUnit 5. Anotācija @Testcontainers ir daļa no paplašinājumiem, kas kontrolē konteinerus testa vidē. Tie atrod visus laukus ar @Container anotāciju un attiecīgi start un stop konteinerus.
Testi ar Spring Boot
Kā jau iepriekš minēju, projektā izmantoju Spring Boot. Šajā gadījumā mums ir jāuzraksta nedaudz vairāk koda. Pirmais solis ir izveidot papildu konfigurācijas klasi.
Šī klase aizstāj esošās īpašības ar vērtībām no klases testa konteiners. Pirmās trīs īpašības ir standarta Spring īpašības. Nākamās piecas ir papildu, pielāgotas īpašības, kuras var izmantot, lai konfigurētu citus resursus un paplašinājumus, piemēram, liquibase:
Tagad ir pienācis laiks definēt vienkāršu integrācijas testu.
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureTestDatabase(replace = NONE)
@ContextConfiguration(initializers = ContainerInit.class)
@Testcontainers
class DummyRepositoryTest {
@Autowired
private DummyRepository;
@Test
void shouldReturnDummy() {
var byId = dummyRepository.getById(10L);
var expected = new Dummy();
expected.setId(10L);
assertThat(byId).completes().emitsCount(1).emits(expected);
}
}
Šeit ir dažas papildu anotācijas.
@SpringBootTest(webEnvironment = RANDOM_PORT) - atzīmē testu kā Spring Boot testu un uzsāk spring kontekstu.
@AutoConfigureTestDatabase(aizstāt = NAV) - šīs anotācijas norāda, ka pavasara testa paplašinājumam nevajadzētu aizstāt postgres datubāzes konfigurāciju ar H2 atmiņas konfigurācijā.
@ContextConfiguration(initializers = ContainerInit.class) - papildu pavasara konteksts konfigurācija, kurā mēs iestatām īpašības no Testa konteineri.
@Testcontainers - kā minēts iepriekš, šī anotācija kontrolē konteinera dzīves ciklu.
Šajā piemērā es izmantoju reaktīvos repozitorijus, bet tas darbojas tāpat arī ar parastajiem JDBC un JPA repozitorijiem.
Tagad varam palaist šo testu. Ja tas ir pirmais palaidums, dzinējam ir jāvelk attēli no docker.hub. Tas var aizņemt brīdi. Pēc tam mēs redzēsim, ka ir palaisti divi konteineri. Viens no tiem ir postgres, bet otrs ir Testcontainers kontrolieris. Šis otrais konteiners pārvalda darbojošos konteinerus, un, pat ja JVM negaidīti apstājas, tas izslēdz konteinerus un sakopj vidi.
Apkoposim
Testa konteineri ir ļoti ērti lietojami rīki, kas palīdz mums izveidot integrācijas testus, kuros tiek izmantoti Docker konteineri. Tas mums sniedz lielāku elastību un palielina izstrādes ātrumu. Pareiza testu konfigurācijas iestatīšana samazina laiku, kas nepieciešams, lai uzņemtu jaunus izstrādātājus. Viņiem nav jākonfigurē visas atkarības, vienkārši jāpalaiž uzrakstītie testi ar izvēlētiem konfigurācijas failiem.