Files
api_test/docs/CRUD_CHAINING_GUIDE.md
T
kankys 5429e9a1ce docs: add CRUD chaining guide for Bruno tests
- Complete step-by-step guide for creating CRUD test chains
- Examples for /spells and /characters endpoints
- Includes troubleshooting section
- References to Bruno documentation

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-15 23:16:11 +02:00

335 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🔗 CRUD Testovací Řetězec v Bruno – Kompletní průvodce
CRUD (Create, Read, Update, Delete) řetězení umožňuje **testovat celý životní cyklus** jednoho záznamu napříč více požadavky. V Bruno se to dělá pomocí **sdílených proměnných prostředí** a **post-response skriptů**.
---
## 🎯 Princip řetězení v Bruno
```
POST /spells → Vytvoří kouzlo → Uloží ID do proměnné
↓
GET /spells/:id → Získá kouzlo → Ověří vytvoření
↓
PUT /spells/:id → Upraví kouzlo → Ověří úpravu
↓
DELETE /spells/:id → Smaže kouzlo → Ověří smazání
↓
GET /spells/:id → Získá kouzlo → Ověří 404 (smazáno)
```
**Klíčové prvky:**
- `bru.setEnvVar("variableName", value)` – Ukládá hodnotu do proměnných prostředí
- `{{variableName}}` – Používá uloženou hodnotu v dalších požadavcích
- **Pořadí (seq)** – Určuje, v jakém pořadí se testy spouštějí
---
## 📝 Krok za krokem: CRUD pro /spells
### Předpoklady
- Backend PotterAPI běží na `localhost:3000`
- Kolekce `PotterAPI` existuje
---
### Krok 1: Vytvoř složku pro CRUD testy
```bash
mkdir -p apiTest/PotterAPI/CRUD
```
---
### Krok 2: Vytvoř folder.yml
```yaml
# apiTest/PotterAPI/CRUD/folder.yml
info:
name: CRUD - Spells
type: folder
seq: 10
request:
auth: inherit
```
---
### Krok 3: Vytvoř test pro CREATE (POST)
```yaml
# apiTest/PotterAPI/CRUD/1-CREATE-spell.yml
info:
name: CREATE - Create new spell
type: http
seq: 1
http:
method: POST
url: http://localhost:3000/spells
auth: inherit
headers:
- name: Content-Type
value: application/json
body:
raw: |-
{
"spell": "Lumos Maximus",
"type": "Charm",
"effect": "Creates bright light",
"isUnforgivable": false
}
runtime:
scripts:
# Uloží ID nově vytvořeného kouzla
- type: post-response
code: |-
if (res.getStatus() === 201) {
const body = res.getBody();
bru.setEnvVar("createdSpellId", body.spell.id);
bru.setEnvVar("createdSpellName", body.spell.spell);
}
# Testy pro vytvoření
- type: tests
code: |-
test("Status code is 201 Created", function() {
expect(res.getStatus()).to.equal(201);
});
test("Response contains spell with id", function() {
const body = res.getBody();
expect(body.spell).to.have.property("id");
expect(body.spell.id).to.be.a("string");
});
settings:
encodeUrl: true
timeout: 10000
```
---
### Krok 4: Vytvoř test pro READ (GET)
```yaml
# apiTest/PotterAPI/CRUD/2-READ-spell.yml
info:
name: READ - Get created spell
type: http
seq: 2
http:
method: GET
url: http://localhost:3000/spells/{{createdSpellId}}
auth: inherit
runtime:
scripts:
- type: tests
code: |-
test("Status code is 200 OK", function() {
expect(res.getStatus()).to.equal(200);
});
test("Response contains the created spell", function() {
const body = res.getBody();
expect(body.spell).to.equal(bru.getEnvVar("createdSpellName"));
expect(body.id).to.equal(bru.getEnvVar("createdSpellId"));
});
settings:
encodeUrl: true
timeout: 10000
```
---
### Krok 5: Vytvoř test pro UPDATE (PUT)
```yaml
# apiTest/PotterAPI/CRUD/3-UPDATE-spell.yml
info:
name: UPDATE - Update spell
type: http
seq: 3
http:
method: PUT
url: http://localhost:3000/spells/{{createdSpellId}}
auth: inherit
headers:
- name: Content-Type
value: application/json
body:
raw: |-
{
"spell": "Lumos Maximus Updated",
"type": "Charm",
"effect": "Creates very bright light",
"isUnforgivable": false
}
runtime:
scripts:
- type: post-response
code: |-
if (res.getStatus() === 201) {
bru.setEnvVar("createdSpellName", "Lumos Maximus Updated");
}
- type: tests
code: |-
test("Status code is 201 Updated", function() {
expect(res.getStatus()).to.equal(201);
});
test("Response contains updated spell", function() {
const body = res.getBody();
expect(body.spell).to.equal("Lumos Maximus Updated");
});
settings:
encodeUrl: true
timeout: 10000
```
---
### Krok 6: Vytvoř test pro DELETE
```yaml
# apiTest/PotterAPI/CRUD/4-DELETE-spell.yml
info:
name: DELETE - Delete spell
type: http
seq: 4
http:
method: DELETE
url: http://localhost:3000/spells/{{createdSpellId}}
auth: inherit
runtime:
scripts:
- type: tests
code: |-
test("Status code is 200 OK", function() {
expect(res.getStatus()).to.equal(200);
});
test("Response contains delete message", function() {
const body = res.getBody();
expect(body.message).to.equal("spell deleted");
});
settings:
encodeUrl: true
timeout: 10000
```
---
### Krok 7: Vytvoř test pro ověření smazání
```yaml
# apiTest/PotterAPI/CRUD/5-VERIFY-deleted.yml
info:
name: VERIFY - Check spell is deleted
type: http
seq: 5
http:
method: GET
url: http://localhost:3000/spells/{{createdSpellId}}
auth: inherit
runtime:
scripts:
- type: tests
code: |-
test("Status code is 404 Not Found", function() {
expect(res.getStatus()).to.equal(404);
});
settings:
encodeUrl: true
timeout: 10000
```
---
## 🚀 Jak to spustit
### Spuštění celého CRUD řetězce
```bash
cd apiTest/PotterAPI
npx @usebruno/cli run CRUD -r
```
---
## 💡 Pokročilé techniky
### 1. Více řetězců v jedné kolekci
Můžeš vytvořit několik nezávislých CRUD řetězců (např. pro různé typy kouzel).
### 2. Sdílené proměnné napříč kolekcemi
Proměnné prostředí (`bru.setEnvVar`) jsou **globální** pro celou kolekci.
### 3. Čištění po testu
Pro idempotentní testy (které lze opakovat):
```javascript
// V poslední fázi řetězce
bru.setEnvVar("createdSpellId", null);
bru.setEnvVar("createdSpellName", null);
```
---
## 📌 Kompletní příklad pro /characters
**⚠️ Důležité:** `/characters` endpoint vyžaduje **Basic Auth**!
```yaml
# 1-CREATE-character.yml
http:
method: POST
url: http://localhost:3000/characters
auth: inherit
headers:
- name: Content-Type
value: application/json
body:
raw: |-
{
"name": "Test Character",
"role": "student",
"house": "Gryffindor",
"school": "Hogwarts"
}
runtime:
scripts:
- type: post-response
code: |-
if (res.getStatus() === 201) {
const body = res.getBody();
bru.setEnvVar("createdCharacterId", body.character.id);
}
```
---
## 🔧 Řešení problémů
| Problém | Příčina | Řešení |
|---------|---------|--------|
| Proměnná je `undefined` | Špatné pořadí `seq` | Zkontroluj, že CREATE má `seq: 1` |
| 404 na CREATE | Špatná URL | Zkontroluj, že URL je `http://localhost:3000/spells` |
| 400 na CREATE | Duplicitní data | Použij unikátní názvy |
| Testy selhávají | Backend neběží | Spusť `npm run start:potter-api` |
| "You can run only..." | Špatný adresář | Spusť z `apiTest/PotterAPI/` |
---
## 📚 Dokumentace
- [Bruno - Environment Variables](https://www.usebruno.com/docs/collections/environments)
- [Bruno - Scripting](https://www.usebruno.com/docs/scripting)
- [Chai Assertions](https://www.chaijs.com/api/bdd/)