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>
This commit is contained in:
kankys committed 2026-09-15 23:16:11 +02:00
1 parent ada38f5dc5
commit 5429e9a1ce
1 file changed
+335
+335
View File
@@ -0,0 +1,335 @@
# 🔗 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/)