Jatkuva testaus mikropalveluilla (esimerkein)
Milloin Microservice Architecture on oikea tie?
Oikean arkkitehtuurin valitseminen ja suunnittelu järjestelmälle on ratkaisevan tärkeää. Palveluvaatimusten laatu ja ei-toiminnallisten vaatimusten, kuten ylläpidettävyys, laajennettavuus ja testattavuus, käsittely on varmistettava.
Mikropalveluarkkitehtuuri on melko toistuva valinta uusimmissa ekosysteemeissä sen jälkeen, kun yritykset ovat ottaneet käyttöön Agilen ja DevOpsin. Vaikka se ei ole tosiasiallinen valinta, se on yksi suosituimmista vaihtoehdoista, kun käsitellään järjestelmiä, jotka kasvavat voimakkaasti ja joissa monoliittiarkkitehtuuria ei enää voida ylläpitää. Komponenttien pitäminen palvelukeskeisinä ja löyhästi kytkettyinä mahdollistaa jatkuvan kehitys- ja julkaisusyklin. Tämä saa yritykset jatkuvasti testaamaan ja päivittämään ohjelmistojaan.
Tärkeimmät edellytykset tällaiselle arkkitehtuurille ovat:
- Verkkotunnuslähtöinen suunnittelu
- Jatkuva toimitus ja DevOps-kulttuuri
- Epäonnistumisen eristäminen
- Hajauttaminen
Sillä on seuraavat edut:
- Joukkueen omistus
- Säännölliset julkaisut
- Helpompi huolto
- Helpommat päivitykset uudempiin versioihin
- Teknologiaagnostikko
Sillä on seuraavat haitat:
- mikropalveluiden väliset viestintämekanismit
- Palvelujen määrän lisääminen lisää järjestelmän yleistä monimutkaisuutta
Mitä hajautetumpi ja monimutkaisempi arkkitehtuuri on, sitä haastavampaa on varmistaa, että järjestelmää voidaan laajentaa ja ylläpitää samalla kun kustannukset ja riskit hallitaan. Yksi liiketapahtuma voi sisältää useita protokollien ja tekniikoiden yhdistelmiä. Kyse ei ole vain käyttötapauksista, vaan myös sen toiminnasta. Agile- ja DevOps-lähestymistapoja otettaessa tulee löytää tasapaino joustavuuden ja toiminnallisuuden välillä jatkuvan päivityksen ja testauksen saavuttamiseksi.

Testausstrategioiden merkitys suhteessa mikropalveluihin
DevOpsin käyttöönotto organisaatiossa pyrkii eliminoimaan eri eristyneitä osastoja ja siirtymään kohti yhtä kokonaisvaltaista tiimiä. Tällä siirrolla pyritään erityisesti parantamaan ohjelmistotiimin ja toimintatiimin välisiä suhteita ja prosesseja. Nopeampi toimitus tarkoittaa myös jatkuvan testauksen varmistamista osana ohjelmistojen toimitusprosessia. Päivittäinen (ja joissakin tapauksissa jopa parin tunnin välein) käyttöönotto on yksi tärkeimmistä tavoitteista nopeassa päästä päähän -yritysratkaisujen toimittamiselle. Luotettavuus ja turvallisuus on pidettävä tässä mielessä, ja tässä on testaus.
Testilähtöisen kehityksen sisällyttäminen on ainoa tapa saavuttaa aito luottamus siihen, että koodi on tuotantovalmis. Kelvolliset testitapaukset lisäävät arvoa järjestelmälle, koska ne validoivat ja dokumentoivat itse järjestelmän. Tämän lisäksi hyvä koodin kattavuus rohkaisee parannuksiin ja auttaa uudelleenmuodostuksessa.
Mikropalveluarkkitehtuuri hajauttaa viestintäkanavat, mikä tekee testauksesta monimutkaisempaa. Se ei ole ylitsepääsemätön ongelma. Mikropalvelun omistavan tiimin ei pitäisi pelätä muutosten tekemistä, koska ne saattavat rikkoa olemassa olevia asiakassovelluksia. Manuaalinen testaus on erittäin tehotonta, kun otetaan huomioon, että jatkuva integrointi ja jatkuva käyttöönotto ovat tämän hetken paras käytäntö. DevOps-insinöörien tulee varmistaa, että automaatiotestit sisällytetään kehitystyönkulkuunsa: kirjoita testejä, lisää/muuta koodia ja suorita testejä.
Yleiset mikropalvelutestausmenetelmät
Testipyramidi on helppo konsepti, joka auttaa tunnistamaan testien kirjoittamisen vaatiman vaivan ja sen, mihin testien määrän pitäisi laskea, jos rakeisuus pienenee. Se pätee myös silloin, kun harkitaan jatkuvaa mikropalvelujen testausta.

Aiheen konkretisoimiseksi käsittelemme esimerkkimikropalvelun testausta Spring Bootilla ja Javalla. Mikropalveluarkkitehtuurit ovat rakenteeltaan monimutkaisempia kuin monoliittinen arkkitehtuuri. Siitä huolimatta keskitymme jatkossakin testityyppiin emmekä arkkitehtuuriin. Katkelmamme perustuvat minimaaliseen projektiin, joka koostuu yhdestä API-pohjaisesta mikropalvelusta, joka omistaa MongoDB:tä käyttävän tietosäilön.
Yksikkötestit
Yksikkötestien tulisi olla suurin osa testeistä, koska ne ovat nopeita, luotettavia ja helppoja ylläpitää. Näitä testejä kutsutaan myös valkoisen laatikon testeiksi. Niitä toteuttava insinööri tuntee logiikan ja kirjoittaa testin vahvistaakseen moduulin tekniset tiedot ja tarkistaakseen koodin laadun.
Näiden testien painopiste on pieni osa järjestelmää erillään, eli Class Under Test (CUT). Yhden vastuun periaate on hyvä ohje toiminnallisuuteen liittyvän koodin hallinnassa.
Yksikkötestin yleisin muoto on "yksinäinen yksikkötesti". ”Se ei ylitä mitään rajoja eikä tarvitse yhteistyökumppaneita CUT:n lisäksi.
Kuten Bill Caputo hahmotteli, tietokannat, viestintäkanavat tai muut järjestelmät ovat rajana; mikä tahansa CUT:n käyttämä tai vaatima lisäluokka on yhteistyökumppani. Yksikkötesti ei saa koskaan ylittää rajoja. Yhteistyökumppaneita käytettäessä kirjoitetaan ”seuraava yksikkötestit. ” CUT:n käyttämien riippuvuuksien pilkkaaminen on tapa testata seurallista koodia "yksinäisen yksikön testillä". ”
Perinteisissä ohjelmistokehitysmalleissa kehittäjien testausta ei vielä otettu villisti käyttöön, vaan se piti testata täysin off-sync-synkronisesti kehityksestä. Korkean koodin peittoluokituksen saavuttamista pidettiin testiohjelmiston luottamuksen avainindikaattorina.
Ketterän ja lyhyiden iteratiivisten syklien käyttöönoton myötä on nyt selvää, että aiemmat testimallit eivät enää toimi. Toistuvia muutoksia odotetaan jatkuvasti. On paljon tärkeämpää testata havaittavaa toimintaa sen sijaan, että kaikki koodipolut katettaisiin. Yksikkötestien tulisi olla enemmän väitteitä kuin koodin kattavuutta, koska tarkoituksena on varmistaa, että logiikka toimii odotetulla tavalla.
On hyödytöntä olla komponentti, jossa on paljon testejä ja suuri prosenttiosuus koodin peitosta, kun testeillä ei ole kunnon väitteitä. BDD (Behavior-Driven Development) -lähestymistavan soveltaminen varmistaa, että testit varmistavat lopputilan ja että käyttäytyminen vastaa yrityksen asettamia vaatimuksia. Kohdennettujen testien, joiden laajuus on hyvin määritelty, etuna on, että epäonnistumisen syy on helpompi tunnistaa. BDD-testit antavat meille enemmän luottamusta siihen, että epäonnistuminen johtui ominaisuuksien käyttäytymisen muutoksesta. Testit, jotka muutoin keskittyvät enemmän koodin kattamiseen, eivät voi tarjota paljon luottamusta, koska on suurempi riski, että epäonnistuminen johtuisi itse testeissä tehdyistä muutoksista koodipolkujen toteutustietojen vuoksi.
Testien tulee noudattaa Martin Fowlerin ehdotusta, kun hän totesi seuraavan (julkaisussa Refactoring: Improving the Design of Existing Code, toinen painos. Kent Beck ja Martin Fowler. Addison-Wesley. 2018):

Toinen syy keskittyä vähemmän pieniin toteutusyksityiskohtiin on refaktorointi. Uudelleenjärjestelyn aikana yksikkötestien tulee antaa meille luottamusta eivätkä hidastaa työtä. Muutos yhteiskäyttäjän toteutuksessa voi johtaa testivirheeseen, mikä voi vaikeuttaa testien ylläpitoa. On erittäin suositeltavaa pitää mahdollisimman vähän seurallisia yksikkötestejä. Tämä pätee erityisesti silloin, kun tällaiset testit saattavat hidastaa kehitystyön elinkaarta, jolloin testit jäävät huomiotta. Erinomainen tilanne seurallisen yksikkötestin sisällyttämiselle on negatiivinen testi, varsinkin kun käsitellään käyttäytymisen todentamista.
Integraatiotestit
Yksi mikropalvelujen merkittävimmistä haasteista on testata niiden vuorovaikutusta muiden infrastruktuuripalvelujen kanssa eli rajojen, joista CUT riippuu, kuten tietokannat tai muut palvelut. Testipyramidi osoittaa selvästi, että integrointitestien tulisi olla vähemmän kuin yksikkötestejä, mutta enemmän kuin komponentteja ja päästä päähän -testejä. Nämä muun tyyppiset testit voivat olla hitaampia, vaikeampia kirjoittaa ja ylläpitää ja olla melko hauraita verrattuna yksikkötesteihin. Rajojen ylittäminen saattaa vaikuttaa suorituskykyyn ja suoritusaikaan verkko- ja tietokantakäytön vuoksi. Silti ne ovat välttämättömiä, etenkin DevOps-kulttuurissa.
Jatkuvassa käyttöönotossa suositaan kapeita integraatiotestejä laajojen integraatiotestien sijaan. Jälkimmäinen on hyvin lähellä päästä päähän -testejä, joissa se vaatii todellisen palvelun olevan käynnissä eikä näiden palvelujen testikaksoisosan käyttöä koodivuorovaikutusten testaamiseen. Päätavoitteena on rakentaa hallittavia operatiivisia testejä nopeasti, helposti ja joustavasti. Integrointitestit keskittyvät CUT:n vuorovaikutukseen yhden palvelun kanssa kerrallaan. Keskitymme kapeisiin integraatiotesteihin. Palveluparin välisen vuorovaikutuksen todentaminen voidaan varmistaa odotetusti, kun palvelut voivat olla joko infrastruktuuripalveluita tai mitä tahansa muuta palvelua.
Pysyvyystestit
>Kiistanalainen testityyppi on pysyvyyskerroksen testaus, jonka ensisijaisena tavoitteena on testata kyselyitä ja vaikutusta testitietoihin. Yksi vaihtoehto on käyttää muistissa olevia tietokantoja. Jotkut saattavat pitää muistissa olevien tietokantojen käyttöä seurallisena yksikkötestinä, koska se on itsenäinen testi, idempotentti ja nopea. Testi suoritetaan tietokannassa, joka on luotu halutulla kokoonpanolla. Kun testiajot ja väitteet on tarkistettu, tietovarasto puhdistetaan automaattisesti, kun JVM poistuu sen lyhytaikaisen luonteen vuoksi. Muista, että yhteys toiseen palveluun on edelleen kesken, ja sitä pidetään kapeana integrointitestinä. Test Driven Development (TDD) -lähestymistavassa tällaiset testit ovat välttämättömiä, koska testipakettien pitäisi suorittaa sekunneissa. Muistissa olevat tietokannat ovat kelvollinen kompromissi sen varmistamiseksi, että testit pidetään mahdollisimman nopeasti, eikä niitä jätetä huomiotta pitkällä aikavälillä.
@Before
public void setup() throws Exception {
try {
// this will download the version of mongo marked as production. One should
// always mention the version that is currently being used by the SUT
String ip = "localhost";
int port = 27017;
IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main. PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6())).build();
MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
mongodExecutable.start();
} catch (IOException e) {
e.printStackTrace();
}
}Katkelma 1: In-memory MongoDB:n asennus ja käynnistys
Yllä oleva ei ole täydellinen integrointitesti, koska muistissa oleva tietokanta ei toimi täsmälleen kuten tuotantotietokantapalvelin. Siksi se ei ole kopio "todelliselle" mongopalvelimelle, mikä olisi tilanne, jos valittaisiin laajat integraatiotestit.
Toinen vaihtoehto pysyvyyden integrointitesteille on suorittaa laajat testit yhdistettynä varsinaiseen tietokantapalvelimeen tai käyttämällä säiliöitä. Kontit helpottavat tuskaa, koska pyynnöstä tietokanta varustetaan kiinteään palvelimeen verrattuna. Muista, että tällaiset testit vievät aikaa, ja testien luokittelu on mahdollinen ratkaisu. Koska nämä testit riippuvat toisesta CUT:n lisäksi toimivasta palvelusta, sitä pidetään järjestelmätestinä. Nämä testit ovat edelleen välttämättömiä, ja luokkien avulla voidaan paremmin määrittää, milloin tietyt testit tulisi suorittaa, jotta kustannusten ja arvon välillä saadaan paras tasapaino. Esimerkiksi kehityssyklin aikana voidaan suorittaa vain kapeita integraatiotestejä käyttämällä muistissa olevaa tietokantaa. Yöversiot voisivat myös suorittaa testejä, jotka kuuluvat johonkin luokkaan, kuten laajaan integraatiotesteihin.
@Category(FastIntegration.class)
@RunWith(SpringRunner.class)
@DataMongoTest
public class DailyTaskRepositoryInMemoryIntegrationTest {
. . .
}
@Category(SlowIntegration.class)
@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class DailyTaskRepositoryIntegrationTest {
...
}Katkelma 2: Luokkien käyttäminen integrointitestien tyyppien erottamiseen
Kuluttajalähtöiset testit
Inter-Process Communication (IPC) -mekanismit ovat yksi mikropalveluarkkitehtuuriin perustuvien hajautettujen järjestelmien keskeinen osa. Tämä asennus aiheuttaa erilaisia komplikaatioita testisarjojen luomisen aikana. Tämän lisäksi ketterässä tiimissä muutoksia tehdään jatkuvasti, mukaan lukien muutokset API:ihin tai tapahtumiin. Riippumatta siitä, mitä IPC-mekanismia järjestelmä käyttää, kahden palvelun välillä on sopimus. Sopimuksia on monenlaisia riippuen siitä, mitä mekanismia järjestelmässä käytetään. Sovellusliittymiä käytettäessä sopimus on HTTP-pyyntö ja vastaus, kun taas tapahtumapohjaisessa järjestelmässä sopimus on itse toimialueen tapahtuma.
Ensisijainen tavoite mikropalveluita testattaessa on varmistaa, että kyseiset sopimukset ovat hyvin määriteltyjä ja vakaita milloin tahansa. TDD:n ylhäältä alas -lähestymistavassa nämä ovat ensimmäiset katettavat testit. Perusteellinen integraatiotesti varmistaa, että kuluttaja saa nopeaa palautetta heti, kun asiakas ei vastaa puhuttavan tuottajan todellista tilaa.
Näiden testien tulisi olla osa säännöllistä käyttöönottoprosessia. Niiden epäonnistuminen antaisi kuluttajille mahdollisuuden saada tieto siitä, että tuottajapuolella on tapahtunut muutos ja että muutoksia tarvitaan, jotta johdonmukaisuus saadaan jälleen aikaan. Ilman tarvetta kirjoittaa monimutkaisia päästä päähän -testejä, "kuluttajalähtöinen sopimustestaus" kohdistuisi tähän käyttötapaukseen.
Seuraavassa on esimerkki spring-cloud-contract-laajennuksen luomasta sopimusvahvistimesta.
@Test
public void validate_add_New_Task() throws Exception {
// given:
MockMvcRequestSpecification request = given()
.header("Content-Type", "application/json;charset=UTF-8")
.body("{"taskName":"newTask","taskDescription":"newDescription","isComplete":false,"isUrgent":true}");
// when:
ResponseOptions response = given().spec(request).post("/tasks");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("['taskName']").isEqualTo("newTask");
assertThatJson(parsedJson).field("['isUrgent']").isEqualTo(true);
assertThatJson(parsedJson).field("['isComplete']").isEqualTo(false);
assertThatJson(parsedJson).field("['id']").isEqualTo("3");
assertThatJson(parsedJson).field("['taskDescription']").isEqualTo("newDescription");
}Katkelma 3: Spring-cloud-contract-laajennuksen automaattisesti luoma sopimusvahvistin
Tuottajaan kirjoitettu BaseClass ohjeistaa, millaista vastausta voidaan odottaa erityyppisiin pyyntöihin käyttämällä itsenäistä asennusta. Pakattu tykkikokoelma on kaikkien kuluttajien käytettävissä, jotta ne voivat vetää niitä käyttöönsä. Monimutkaisuus syntyy, kun useat kuluttajat käyttävät samaa sopimusta; siksi tuottajalla on oltava kokonaiskuva vaadituista palvelusopimuksista.
@RunWith(SpringRunner.class)
@SpringBootTest
public class ContractBaseClass {
@Autowired
private DailyTaskController taskController;
@MockBean
private DailyTaskRepository dailyTaskRepository;
@Before
public void before() {
RestAssuredMockMvc.standaloneSetup(this.taskController);
Mockito.when(this.dailyTaskRepository.findById("1")).thenReturn(
Optional.of(new DailyTask("1", "Test", "Description", false, null)));
. . .
Mockito.when(this.dailyTaskRepository.save(
new DailyTask(null, "newTask", "newDescription", false, true))).thenReturn(
new DailyTask("3", "newTask", "newDescription", false, true));
}Katkelma 4: tuottajan BaseClass, joka määrittää kunkin pyynnön odotetun vastauksen
Kuluttajapuolella kevät-pilvi-käynnistin-sopimus-stub-runner-riippuvuus sisällytettiin, joten määritimme testin käyttämään stubs-binääriä. Tämä testi suoritetaan käyttämällä tuottajan luomia tyngöitä kokoonpanon mukaan, jonka versio on määritetty tai aina uusin. Tynkä artefakti yhdistää asiakkaan tuottajaan varmistaakseen, että molemmat työskentelevät saman sopimuksen mukaisesti. Mikä tahansa tapahtuva muutos heijastuisi näihin testeihin, ja siten kuluttaja tunnistaisi, onko tuottaja muuttunut vai ei.
@SpringBootTest(classes = TodayAskApplication.class)
@RunWith(SpringRunner.class)
@AutoConfigureStubRunner(ids = "com.cwie.arch:today:+:stubs:8080", stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class TodayClientStubTest {
. . .
@Test
public void addTask_expectNewTaskResponse () {
Task newTask = todayClient.createTask(
new Task(null, "newTask", "newDescription", false, true));
BDDAssertions.then(newTask).isNotNull();
BDDAssertions.then(newTask.getId()).isEqualTo("3");
. . .
}
}Katkelma 5: Kuluttaja lisää tuottajan määrittämän tynkäversion
Tällaiset integrointitestit varmistavat, että palveluntarjoajan API on edelleen kuluttajien odotusten mukainen. Käytettäessä sovellusliittymien pilkattuja yksikkötestejä olisimme tukahduttaneet API:t ja pilkanneet toimintaa. Kuluttajan näkökulmasta tämäntyyppiset testit varmistavat, että asiakas vastaa odotuksiamme. On tärkeää huomata, että jos tuottajapuoli muuttaa API:ta, testit eivät epäonnistu. Ja on välttämätöntä määritellä, mitä testi kattaa.
// the response we expect is represented in the task1.json file
private Resource taskOne = new ClassPathResource("task1.json");
@Autowired
private TodayClient todayClient;
@Test
public void createNewTask_expectTaskIsCreated() {
WireMock.stubFor(WireMock.post(WireMock.urlMatching("/tasks"))
.willReturn(WireMock.aResponse()
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
.withStatus(HttpStatus.OK.value())
.withBody(transformResourceJsonToString(taskOne))));
Task tasks = todayClient.createTask(new Task(null, "runUTest", "Run Test", false, true));
BDDAssertions.then(tasks.getId()).isEqualTo("1");Katkelma 6: kuluttajatesti, joka tekee väitteitä omasta määritellystä vastauksestaan
Komponenttitestit
Mikropalveluarkkitehtuuri voi kasvaa nopeasti, joten testattava komponentti saattaa integroitua useisiin muihin komponentteihin ja useisiin infrastruktuuripalveluihin. Tähän asti olemme kattaneet valkoisen laatikon testauksen yksikkötesteillä ja kapeilla integraatiotesteillä testataksemme CUT:n rajan ylittävää integrointia toiseen palveluun.
Nopein komponenttien testaustyyppi on prosessin sisäinen lähestymistapa, jossa testauskaksojen ja muistin tietovarastojen käytön ohella testaus pysyy rajojen sisällä. Tämän lähestymistavan suurin haittapuoli on, että käyttöön otettavaa tuotantopalvelua ei ole täysin testattu; päinvastoin, komponentti vaatii muutoksia sovelluksen kytkemiseksi eri tavalla. Suositeltu menetelmä on prosessin ulkopuolisten komponenttien testaus. Nämä ovat kuin päästä päähän -testejä, mutta kun kaikki ulkoiset yhteistyökumppanit on vaihdettu testituplaan, se harjoittelee siten täysin käyttöön otettua artefaktia hyödyntäen todellisia verkkopuheluita. Testi olisi vastuussa siitä, että kaikki ulkoiset palvelut määritetään oikein tyngiksi.
@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TodayConfiguration.class, TodayIntegrationApplication.class,
CloudFoundryClientConfiguration.class })
public class BaseFunctionalitySteps {
@Autowired
private CloudFoundryOperations cf;
private static File manifest = new File(".manifest.yml");
@Autowired
private TodayClient client;
// Any stubs required
. . .
public void setup() {
cf.applications().pushManifest(PushApplicationManifestRequest.builder()
.manifest(ApplicationManifestUtils.read(manifest.toPath()).get(0)).build()).block();
}
. . .
// Any calls required by tests
public void requestForAllTasks() {
this.client.getTodoTasks();
}
}Katkelma 7: Luettelon käyttöönotto CloudFoundryssa ja kaikki testien edellyttämät kutsut
Cloud Foundry on yksi vaihtoehdoista, joita käytetään konttipohjaisissa testausarkkitehtuureissa. "Se on avoimen lähdekoodin pilvisovellusalusta, joka tekee sovellusten rakentamisesta, testaamisesta, käyttöönotosta ja skaalaamisesta nopeampaa ja helpompaa. ” Seuraava on manifest.yml, tiedosto, joka määrittää kaikkien järjestelmän sovellusten määritykset. Tätä tiedostoa käytetään todellisen palvelun käyttöönottoon tuotantovalmiissa muodossa Pivotal-organisaation tilassa, jossa MongoDB-palvelu on jo määritetty tuotantoversiota vastaavasti.
---
applications:
- name: today
instances: 1
path: ../today/target/today-0.0.1-SNAPSHOT.jar
memory: 1024M
routes:
- route: today.cfapps.io
services:
- mongo-itKatkelma 8: Palvelun yhden esiintymän käyttöönotto mongo-palvelusta riippuen
Kun valitset prosessin ulkopuolisen lähestymistavan, muista, että todellisia rajoja testataan, ja näin ollen testit ovat hitaampia, koska siellä on verkko- ja tietokantavuorovaikutuksia. Olisi ihanteellista, että nämä testisarjat kirjoitettaisiin erillisessä moduulissa. Jotta niitä voidaan ajaa erikseen eri maven-vaiheessa tavallisen "testi"-vaiheen sijaan.
Koska testien painopiste on itse komponentissa, testit kattavat komponentin ensisijaiset vastuut, mutta laiminlyövät tarkoituksellisesti kaikki muut järjestelmän osat.
Kurkku, ohjelmistotyökalu, joka tukee Behavior-Driven Developmentia, on vaihtoehto tällaisten käyttäytymistestien määrittämiseen. Selkeän kielen jäsentimen, Gherkin, avulla se varmistaa, että asiakkaat ymmärtävät helposti kaikki kuvatut testit. Seuraava Cucumber-ominaisuustiedosto varmistaa, että komponenttitoteutus vastaa kyseisen ominaisuuden liiketoimintavaatimuksia.
Feature: Tasks
Scenario: Retrieving one task from list
Given the component is running
And the data consists of one or more tasks
When user requests for task x
Then the correct task x is returned
Scenario: Retrieving all lists
Given the data consists of one or more tasks
When user requests for all tasks
Then all tasks in database are returned
Scenario: Negative Test
Given the component is not running
When user requests for task x it fails with response 404Katkelma 9: BDD-testejä määrittelevä ominaisuustiedosto
Päästä päähän -testit
Samoin kuin komponenttitestien, näiden päästä päähän -testien tarkoituksena ei ole suorittaa koodin peittoa, vaan varmistaa, että järjestelmä täyttää vaaditut liiketoimintaskenaariot. Erona on, että päästä päähän -testauksessa kaikki komponentit ovat toiminnassa testin aikana.
Testauspyramidikaavion mukaan päästä päähän -testien määrä laskee edelleen, kun otetaan huomioon niiden aiheuttama hitaus. Ensimmäinen vaihe on käynnistää asennus, ja tässä esimerkissä hyödynnämme dockeria.
version: '3.7'
services:
today-app:
image: today-app:1
container_name: "today-app"
build:
context: ./
dockerfile: DockerFile
environment:
- SPRING_DATA_MONGODB_HOST=mongodb
volumes:
- /data/today-app
ports:
- "8082:8080"
links:
- mongodb
depends_on:
- mongodb
mongodb:
image: mongo:3.2
container_name: "mongodb"
restart: always
environment:
- AUTH=no
- MONGO_DATA_DIR=/data/db
- MONGO_LOG_DIR=/dev/log
volumes:
- ./data:/data
ports:
- 27017:27017
command: mongod --smallfiles --logpath=/dev/null # --quietKatkelma 10: Docker.yml-määritelmä, jota käytetään määritetyn palvelun ja määritetyn mongon version käyttöönottamiseksi säilöinä
Komponenttitestien mukaan on järkevää pitää päästä päähän -testit erillisessä moduulissa ja eri vaiheissa. exec-maven-plugin:lla otettiin käyttöön kaikki vaaditut komponentit, suoritettiin testimme ja lopuksi puhdistettiin ja purettiin testiympäristömme.

Koska tämä on laajapinoinen testi, suoritetaan pienempi valikoima testejä ominaisuutta kohti. Testit valitaan koetun liiketoimintariskin perusteella. Aiemmat testityypit kattoivat matalan tason yksityiskohdat. Tämä tarkoittaa, vastaako käyttäjän tarina hyväksymiskriteerejä. Näiden testien tulisi myös keskeyttää julkaisu välittömästi, koska epäonnistuminen tässä voi aiheuttaa vakavia seurauksia liiketoiminnalle.
Johtopäätös
Handoff-keskeinen testaus on usein erittäin pitkä prosessi, joka kestää jopa viikkoja, ennen kuin kaikki virheet tunnistetaan, korjataan ja uusi käyttöönotto on valmis. Palautetta saadaan vasta julkaisun jälkeen, mikä tekee versiomme elinkaaren nopeimman mahdollisen läpimenoajan.
Jatkuva testaustapa takaa välittömän palautteen. Tämä tarkoittaa, että DevOps-insinööri on välittömästi tietoinen siitä, onko toteutettu ominaisuus tuotantovalmis vai ei, riippuen testien tuloksista. Yksikkötesteistä päästä päähän -testeihin ne kaikki auttavat nopeuttamaan arviointiprosessia.
Mikropalveluarkkitehtuuri auttaa luomaan nopeampia käyttöönottoja tuotantoon, koska se on toimialuelähtöinen. Se varmistaa vikaeristyksen ja lisää omistajuutta. Kun useat tiimit työskentelevät saman projektin parissa, se on toinen syy ottaa käyttöön tällainen arkkitehtuuri: Varmistaa, että tiimit ovat riippumattomia eivätkä häiritse toistensa työtä.
Paranna testattavuutta siirtymällä kohti jatkuvaa testausta. Jokaisella mikropalvelulla on hyvin määritelty toimialue, ja sen laajuus tulisi rajoittaa yhteen toimijaan. Käytetyt testitapaukset ovat tarkkoja ja ytimekkäämpiä, ja testit ovat erillisiä, mikä helpottaa julkaisuja ja nopeampaa käyttöönottoa.
TDD-lähestymistavan mukaisesti koodausta ei tapahdu, ellei epäonnistunut testi palaa. Tämä prosessi lisää luottamusta, kun iteratiivinen toteutus johtaa onnistuneeseen kokeiluun. Tämä prosessi tarkoittaa, että testaus tapahtuu rinnakkain varsinaisen toteutuksen kanssa ja kaikki yllä mainitut testit suoritetaan ennen kuin muutokset saavuttavat lavastusympäristön. Jatkuva testaus kehittyy, kunnes se siirtyy seuraavaan julkaisuvaiheeseen eli lavastusympäristöön, jossa painopiste siirtyy kattavampaan testaukseen, kuten kuormitustestaukseen.
Ketterä, DevOps ja jatkuva toimitus edellyttävät jatkuvaa testausta. Tärkein etu on automaattisista testeistä saatu välitön palaute. Mahdolliset vaikutukset voivat vaikuttaa käyttökokemukseen, mutta niillä voi olla myös riskialttiita seurauksia liiketoiminnalle. Jos haluat lisätietoja jatkuvasta testauksesta, ota yhteyttä phoenixNAPiin jo tänään.