Išsamus integracinio testavimo vadovas, skirtas API testavimui su Supertest. Apžvelgiama sąranka, gerosios praktikos ir pažangios technikos.
Integracinis testavimas: API testavimo įvaldymas su Supertest
Programinės įrangos kūrimo srityje labai svarbu užtikrinti, kad atskiri komponentai veiktų teisingai atskirai (vienetų testavimas). Tačiau lygiai taip pat svarbu patikrinti, ar šie komponentai sklandžiai veikia kartu. Būtent čia pasitelkiamas integracinis testavimas. Integracinis testavimas skirtas patvirtinti sąveiką tarp skirtingų modulių ar paslaugų programoje. Šiame straipsnyje gilinamasi į integracinį testavimą, ypač daug dėmesio skiriant API testavimui su Supertest – galinga ir patogia biblioteka, skirta testuoti HTTP tvirtinimus Node.js aplinkoje.
Kas yra integracinis testavimas?
Integracinis testavimas – tai programinės įrangos testavimo tipas, kai atskiri programinės įrangos moduliai sujungiami ir testuojami kaip grupė. Jo tikslas – atskleisti defektus integruotų vienetų sąveikose. Skirtingai nuo vienetų testavimo, kuris sutelktas į atskirus komponentus, integracinis testavimas tikrina duomenų ir valdymo srautus tarp modulių. Dažniausi integracinio testavimo metodai:
- „Iš viršaus į apačią“ integracija: Pradedama nuo aukščiausio lygio modulių ir integruojama žemyn.
- „Iš apačios į viršų“ integracija: Pradedama nuo žemiausio lygio modulių ir integruojama aukštyn.
- „Didžiojo sprogimo“ integracija: Visi moduliai integruojami vienu metu. Šis metodas paprastai mažiau rekomenduojamas dėl sunkumų išskiriant problemas.
- „Sumuštinio“ integracija: „Iš viršaus į apačią“ ir „iš apačios į viršų“ integracijos derinys.
API kontekste, integracinis testavimas apima patikrinimą, ar skirtingos API sąsajos teisingai veikia kartu, ar tarp jų perduodami duomenys yra nuoseklūs ir ar visa sistema veikia kaip tikėtasi. Pavyzdžiui, įsivaizduokite elektroninės prekybos programą su atskiromis API produktų valdymui, vartotojų autentifikavimui ir mokėjimų apdorojimui. Integracinis testavimas užtikrintų, kad šios API sąsajos bendrautų teisingai, leisdamos vartotojams naršyti produktus, saugiai prisijungti ir atlikti pirkimus.
Kodėl svarbus API integracinis testavimas?
API integracinis testavimas yra kritiškai svarbus dėl kelių priežasčių:
- Užtikrina sistemos patikimumą: Jis padeda nustatyti integracijos problemas ankstyvame kūrimo etape, užkertant kelią netikėtiems gedimams produkcinėje aplinkoje.
- Patvirtina duomenų vientisumą: Jis patikrina, ar duomenys teisingai perduodami ir transformuojami tarp skirtingų API.
- Gerina programos našumą: Jis gali atskleisti našumo problemas, susijusias su API sąveikomis.
- Stiprina saugumą: Jis gali nustatyti saugumo pažeidžiamumus, kylančius dėl netinkamos API integracijos. Pavyzdžiui, užtikrinant tinkamą autentifikavimą ir autorizavimą, kai API sąsajos bendrauja.
- Mažina kūrimo kaštus: Anksti ištaisyti integracijos problemas yra žymiai pigiau, nei spręsti jas vėlesniuose kūrimo ciklo etapuose.
Apsvarstykite pasaulinę kelionių rezervavimo platformą. API integracinis testavimas yra nepaprastai svarbus siekiant užtikrinti sklandų ryšį tarp API, tvarkančių skrydžių rezervacijas, viešbučių užsakymus ir mokėjimo sistemas iš įvairių šalių. Netinkamai integruotos API gali sukelti neteisingas rezervacijas, mokėjimų gedimus ir prastą vartotojo patirtį, neigiamai paveikdamos platformos reputaciją ir pajamas.
Pristatome Supertest: galingas įrankis API testavimui
Supertest yra aukšto lygio abstrakcija HTTP užklausų testavimui. Ji suteikia patogią ir sklandžią API, skirtą siųsti užklausas į jūsų programą ir tvirtinti atsakymus. Sukurta ant Node.js pagrindo, Supertest yra specialiai skirta testuoti Node.js HTTP serverius. Ji puikiai veikia su populiariomis testavimo sistemomis, tokiomis kaip Jest ir Mocha.
Pagrindinės Supertest savybės:
- Lengva naudoti: Supertest siūlo paprastą ir intuityvią API HTTP užklausoms siųsti ir tvirtinimams atlikti.
- Asinchroninis testavimas: Ji sklandžiai tvarko asinchronines operacijas, todėl idealiai tinka testuoti API, kurios remiasi asinchronine logika.
- Sklandi sąsaja: Ji suteikia sklandžią sąsają, leidžiančią grandinėmis sujungti metodus, kad testai būtų glausti ir lengvai skaitomi.
- Išsamus tvirtinimų palaikymas: Ji palaiko platų tvirtinimų spektrą, skirtą patikrinti atsakymo būsenos kodus, antraštes ir turinį.
- Integracija su testavimo sistemomis: Ji sklandžiai integruojasi su populiariomis testavimo sistemomis, tokiomis kaip Jest ir Mocha, leidžiant jums naudoti esamą testavimo infrastruktūrą.
Testavimo aplinkos paruošimas
Prieš pradedant, paruoškime pagrindinę testavimo aplinką. Manysime, kad turite įdiegtą Node.js ir npm (arba yarn). Naudosime Jest kaip testavimo sistemą ir Supertest API testavimui.
- Sukurkite Node.js projektą:
mkdir api-testing-example
cd api-testing-example
npm init -y
- Įdiekite priklausomybes:
npm install --save-dev jest supertest
npm install express # Arba jūsų pageidaujamą sistemą API kūrimui
- Konfigūruokite Jest: Pridėkite šį kodą į savo
package.json
failą:
{
"scripts": {
"test": "jest"
}
}
- Sukurkite paprastą API galinį punktą: Sukurkite failą pavadinimu
app.js
(ar panašų) su šiuo kodu:
const express = require('express');
const app = express();
const port = 3000;
app.get('/hello', (req, res) => {
res.send('Sveikas, pasauli!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
module.exports = app; // Export for testing
Pirmojo Supertest testo rašymas
Dabar, kai mūsų aplinka paruošta, parašykime paprastą Supertest testą, kad patikrintume savo API galinį punktą. Sukurkite failą pavadinimu app.test.js
(ar panašų) savo projekto šakninėje direktorijoje:
const request = require('supertest');
const app = require('./app');
describe('GET /hello', () => {
it('atsako su 200 OK ir grąžina "Sveikas, pasauli!"', async () => {
const response = await request(app).get('/hello');
expect(response.statusCode).toBe(200);
expect(response.text).toBe('Sveikas, pasauli!');
});
});
Paaiškinimas:
- Importuojame
supertest
ir mūsų Express programą. - Naudojame
describe
, kad sugrupuotume savo testus. - Naudojame
it
, kad apibrėžtume konkretų testo atvejį. - Naudojame
request(app)
, kad sukurtume Supertest agentą, kuris siųs užklausas į mūsų programą. - Naudojame
.get('/hello')
, kad išsiųstume GET užklausą į/hello
galinį punktą. - Naudojame
await
, kad palauktume atsakymo. Supertest metodai grąžina pažadus (promises), leidžiančius mums naudoti async/await švaresniam kodui. - Naudojame
expect(response.statusCode).toBe(200)
, kad patvirtintume, jog atsakymo būsenos kodas yra 200 OK. - Naudojame
expect(response.text).toBe('Sveikas, pasauli!')
, kad patvirtintume, jog atsakymo turinys yra „Sveikas, pasauli!“.
Norėdami paleisti testą, vykdykite šią komandą savo terminale:
npm test
Jei viskas paruošta teisingai, turėtumėte pamatyti, kad testas sėkmingai įvykdytas.
Pažangios Supertest technikos
Supertest siūlo platų funkcijų spektrą pažangiam API testavimui. Panagrinėkime kai kurias iš jų.
1. Užklausos turinio siuntimas
Norėdami siųsti duomenis užklausos turinyje, galite naudoti .send()
metodą. Pavyzdžiui, sukurkime galinį punktą, kuris priima JSON duomenis:
app.post('/users', express.json(), (req, res) => {
const { name, email } = req.body;
// Imituojame vartotojo kūrimą duomenų bazėje
const user = { id: Date.now(), name, email };
res.status(201).json(user);
});
Štai kaip galite testuoti šį galinį punktą naudodami Supertest:
describe('POST /users', () => {
it('sukuriamas naujas vartotojas', async () => {
const userData = {
name: 'John Doe',
email: 'john.doe@example.com',
};
const response = await request(app)
.post('/users')
.send(userData)
.expect(201);
expect(response.body).toHaveProperty('id');
expect(response.body.name).toBe(userData.name);
expect(response.body.email).toBe(userData.email);
});
});
Paaiškinimas:
- Naudojame
.post('/users')
, kad išsiųstume POST užklausą į/users
galinį punktą. - Naudojame
.send(userData)
, kad išsiųstumeuserData
objektą užklausos turinyje. Supertest automatiškai nustatoContent-Type
antraštę įapplication/json
. - Naudojame
.expect(201)
, kad patvirtintume, jog atsakymo būsenos kodas yra 201 Created. - Naudojame
expect(response.body).toHaveProperty('id')
, kad patvirtintume, jog atsakymo turinyje yraid
savybė. - Naudojame
expect(response.body.name).toBe(userData.name)
irexpect(response.body.email).toBe(userData.email)
, kad patvirtintume, jogname
iremail
savybės atsakymo turinyje atitinka duomenis, kuriuos išsiuntėme užklausoje.
2. Antraščių nustatymas
Norėdami nustatyti pasirinktines antraštes savo užklausose, galite naudoti .set()
metodą. Tai naudinga nustatant autentifikavimo raktus, turinio tipus ar kitas pasirinktines antraštes.
describe('GET /protected', () => {
it('reikalauja autentifikacijos', async () => {
const response = await request(app).get('/protected').expect(401);
});
it('grąžina 200 OK su galiojančiu raktu', async () => {
// Imituojame galiojančio rakto gavimą
const token = 'valid-token';
const response = await request(app)
.get('/protected')
.set('Authorization', `Bearer ${token}`)
.expect(200);
expect(response.text).toBe('Apsaugotas išteklius');
});
});
Paaiškinimas:
- Naudojame
.set('Authorization', `Bearer ${token}`)
, kad nustatytumeAuthorization
antraštę įBearer ${token}
.
3. Slapukų tvarkymas
Supertest taip pat gali tvarkyti slapukus. Galite nustatyti slapukus naudodami .set('Cookie', ...)
metodą arba galite naudoti .cookies
savybę, kad pasiektumėte ir modifikuotumėte slapukus.
4. Failų įkėlimo testavimas
Supertest gali būti naudojamas testuoti API galinius punktus, kurie tvarko failų įkėlimus. Galite naudoti .attach()
metodą, kad pridėtumėte failus prie užklausos.
5. Tvirtinimo bibliotekų naudojimas (Chai)
Nors Jest integruota tvirtinimo biblioteka daugeliu atvejų yra pakankama, su Supertest galite naudoti ir galingesnes tvirtinimo bibliotekas, tokias kaip Chai. Chai suteikia išraiškingesnę ir lankstesnę tvirtinimo sintaksę. Norėdami naudoti Chai, turėsite jį įdiegti:
npm install --save-dev chai
Tada galite importuoti Chai į savo testo failą ir naudoti jo tvirtinimus:
const request = require('supertest');
const app = require('./app');
const chai = require('chai');
const expect = chai.expect;
describe('GET /hello', () => {
it('atsako su 200 OK ir grąžina "Sveikas, pasauli!"', async () => {
const response = await request(app).get('/hello');
expect(response.statusCode).to.equal(200);
expect(response.text).to.equal('Sveikas, pasauli!');
});
});
Pastaba: Gali tekti sukonfigūruoti Jest, kad jis teisingai veiktų su Chai. Tai dažnai apima sąrankos failo pridėjimą, kuris importuoja Chai ir sukonfigūruoja jį veikti su Jest globaliu expect
.
6. Agentų pakartotinis naudojimas
Testams, kuriems reikia sukurti specifinę aplinką (pvz., autentifikaciją), dažnai naudinga pakartotinai naudoti Supertest agentą. Tai padeda išvengti pasikartojančio sąrankos kodo kiekviename testo atvejyje.
describe('Autentifikuoti API testai', () => {
let agent;
beforeAll(() => {
agent = request.agent(app); // Sukuriame nuolatinį agentą
// Imituojame autentifikaciją
return agent
.post('/login')
.send({ username: 'testuser', password: 'password123' });
});
it('gali pasiekti apsaugotą išteklių', async () => {
const response = await agent.get('/protected').expect(200);
expect(response.text).toBe('Apsaugotas išteklius');
});
it('gali atlikti kitus veiksmus, reikalaujančius autentifikacijos', async () => {
// Čia atlikite kitus autentifikuotus veiksmus
});
});
Šiame pavyzdyje, mes sukuriame Supertest agentą beforeAll
etape ir jį autentifikuojame. Vėlesni testai describe
bloke gali pakartotinai naudoti šį autentifikuotą agentą, nereikalaujant pakartotinės autentifikacijos kiekvienam testui.
Geriausios API integracinio testavimo su Supertest praktikos
Norėdami užtikrinti efektyvų API integracinį testavimą, apsvarstykite šias geriausias praktikas:
- Testuokite visą darbo eigą (end-to-end): Sutelkite dėmesį į visų vartotojo darbo eigų testavimą, o ne į pavienius API galinius punktus. Tai padeda nustatyti integracijos problemas, kurios gali būti nepastebimos testuojant atskiras API.
- Naudokite realistiškus duomenis: Savo testuose naudokite realistiškus duomenis, kad imituotumėte realaus pasaulio scenarijus. Tai apima galiojančių duomenų formatų, ribinių verčių ir galbūt neteisingų duomenų naudojimą klaidų tvarkymui testuoti.
- Izoliuokite savo testus: Užtikrinkite, kad jūsų testai būtų nepriklausomi vienas nuo kito ir kad jie nesiremtų bendra būsena. Tai padarys jūsų testus patikimesnius ir lengviau derinamus. Apsvarstykite galimybę naudoti atskirą testavimo duomenų bazę arba imituoti išorines priklausomybes.
- Imituokite išorines priklausomybes: Naudokite imitavimą (mocking), kad izoliuotumėte savo API nuo išorinių priklausomybių, tokių kaip duomenų bazės, trečiųjų šalių API ar kitos paslaugos. Tai padarys jūsų testus greitesnius ir patikimesnius, taip pat leis testuoti skirtingus scenarijus, nepriklausomai nuo išorinių paslaugų prieinamumo. Bibliotekos, tokios kaip
nock
, yra naudingos HTTP užklausoms imituoti. - Rašykite išsamius testus: Siekite išsamaus testų padengimo, įskaitant pozityvius testus (patikrinant sėkmingus atsakymus), negatyvius testus (patikrinant klaidų tvarkymą) ir ribinius testus (patikrinant kraštutinius atvejus).
- Automatizuokite savo testus: Integruokite savo API integracinius testus į savo nuolatinės integracijos (CI) konvejerį, kad užtikrintumėte, jog jie būtų automatiškai paleidžiami kiekvieną kartą, kai atliekami pakeitimai kodo bazėje. Tai padės anksti nustatyti integracijos problemas ir užkirsti kelią joms patekti į produkcinę aplinką.
- Dokumentuokite savo testus: Aiškiai ir glaustai dokumentuokite savo API integracinius testus. Tai padės kitiems kūrėjams lengviau suprasti testų tikslą ir juos prižiūrėti laikui bėgant.
- Naudokite aplinkos kintamuosius: Saugokite jautrią informaciją, pvz., API raktus, duomenų bazių slaptažodžius ir kitas konfigūracijos vertes, aplinkos kintamuosiuose, o ne koduokite jų tiesiogiai savo testuose. Tai padarys jūsų testus saugesnius ir lengviau konfigūruojamus skirtingoms aplinkoms.
- Apsvarstykite API kontraktus: Naudokite API kontraktų testavimą, kad patvirtintumėte, jog jūsų API atitinka apibrėžtą kontraktą (pvz., OpenAPI/Swagger). Tai padeda užtikrinti suderinamumą tarp skirtingų paslaugų ir išvengti pakeitimų, kurie sugadintų sistemą. Įrankiai, tokie kaip Pact, gali būti naudojami kontraktų testavimui.
Dažniausios klaidos, kurių reikia vengti
- Testų neizoliavimas: Testai turi būti nepriklausomi. Venkite priklausomybės nuo kitų testų rezultatų.
- Įgyvendinimo detalių testavimas: Sutelkite dėmesį į API elgseną ir kontraktą, o ne į jos vidinį įgyvendinimą.
- Klaidų tvarkymo ignoravimas: Kruopščiai patikrinkite, kaip jūsų API tvarko neteisingus įvesties duomenis, kraštutinius atvejus ir netikėtas klaidas.
- Autentifikavimo ir autorizavimo testavimo praleidimas: Užtikrinkite, kad jūsų API saugumo mechanizmai būtų tinkamai išbandyti, siekiant išvengti neautorizuotos prieigos.
Išvada
API integracinis testavimas yra esminė programinės įrangos kūrimo proceso dalis. Naudodami Supertest, galite lengvai rašyti išsamius ir patikimus API integracinius testus, kurie padeda užtikrinti jūsų programos kokybę ir stabilumą. Nepamirškite sutelkti dėmesio į visos darbo eigos testavimą, naudoti realistiškus duomenis, izoliuoti savo testus ir automatizuoti testavimo procesą. Laikydamiesi šių geriausių praktikų, galite žymiai sumažinti integracijos problemų riziką ir pateikti patikimesnį produktą.
Kadangi API ir toliau yra šiuolaikinių programų ir mikropaslaugų architektūrų varomoji jėga, patikimo API testavimo, ypač integracinio testavimo, svarba tik didės. Supertest suteikia galingą ir prieinamą įrankių rinkinį kūrėjams visame pasaulyje, kad jie galėtų užtikrinti savo API sąveikų patikimumą ir kokybę.