Strategija testiranja
merql uporablja model testiranja, ki temelji na referenčnih rezultatih. Vsak testni scenarij določa znan nabor vhodnih podatkov (tri stanja zbirke podatkov), determinističen pričakovani rezultat (referenčni rezultat) in primerja dejanski rezultat združevanja s pričakovanim. 32 scenarijev pokriva čista združevanja, spore, razreševanje identitete, podatkovne tipe, obseg in robne primere.
# Run the full verification suite.
./bin/verify-all
Ukazi na tej strani se izvajajo v kopiji repozitorija merql po
composer install. Razvojni skripti v bin/, korpus scenarios/
in testi niso del paketa Composer. Razvojne odvisnosti vključujejo PHPUnit 13, za katerega je potreben PHP 8.4 ali novejši, čeprav knjižnica sama deluje z PHP 8.2.
Testiranje na podlagi referenčnih rezultatov
Ni obstoječega referenčnega orodja, ki bi izvajalo tristransko združevanje zbirk podatkov, zato se referenčni rezultat izračuna iz znanih vhodnih podatkov, namesto da bi ga ustvarilo zunanje orodje. Vsak scenarij ima determinističen pričakovani rezultat, ki ga je mogoče preveriti z logiko:
- Priprava -- ustvarite tri stanja zbirke podatkov (osnovno stanje, naša kopija, njihova kopija) z znano vsebino.
- Referenčni rezultat -- iz znanih vhodnih podatkov izračunajte pričakovani rezultat združevanja.
- Dejanski rezultat -- izvedite združevanje treh stanj z merql.
- Primerjava -- dejanski rezultat se mora natančno ujemati s pričakovanim.
Known inputs (base, ours, theirs)
| |
Deterministic merql merge
computation
| |
Expected result Actual result
| |
-----> Compare <-----
|
Pass or Fail
Zagon testov
Celovito preverjanje
Skript verify-all je končno preverjanje. Izvede statično analizo, preverjanje standardov kodiranja, teste PHPUnit in regresijsko zbirko referenčnih testov:
./bin/verify-all
To mora uspeti, preden je katero koli delo mogoče šteti za dokončano.
Regresijska zbirka referenčnih testov
Zaženite vseh 32 scenarijev:
./bin/test-regression
Zaženite eno kategorijo:
./bin/test-regression --category clean
./bin/test-regression --category conflict
./bin/test-regression --category identity
Kategorije so imena imenikov pod scenarios/: clean, conflict,
identity, types, scale in edge. Neznana kategorija izpiše
No scenarios found in se uspešno konča. --category lahko ponovite, da zaženete
več kategorij.
Skript sprejme tudi --jobs, vendar vrednost prezre in scenarije zažene
zaporedno (#5).
Zaženite z najmanj izpisa (samo uspeh/neuspeh):
./bin/test-regression --fast
Posamezen scenarij
Preizkusite en scenarij skozi celoten postopek:
./bin/test-scenario column-level-clean
Posamezni koraki referenčnega preizkusa
./bin/oracle column-level-clean # Compute expected result
./bin/actual column-level-clean # Run merql, capture output
./bin/compare column-level-clean # Diff oracle vs actual
Enotski testi
composer test:unit # Isolated component tests
composer test:integration # Integration tests (SQLite, plus MySQL when configured)
composer test # All PHPUnit suites
composer test:oracle # Oracle regression corpus (bin/test-regression)
composer verify # analyse + cs + test + test:oracle
composer test zažene samo PHPUnit. Zbirka oracle PHPUnit kaže na
tests/Oracle, v katerem so razredi za izvajanje scenarijev, vendar ni testnih primerov, zato
se 32 scenarijev zažene samo prek composer test:oracle, composer verify ali
./bin/verify-all.
Integracijski testi MySQL so preskočeni, razen če MERQL_MYSQL_HOST,
MERQL_MYSQL_DATABASE in MERQL_MYSQL_USER (ter po želji
MERQL_MYSQL_PASSWORD in MERQL_MYSQL_PORT) kažejo na testno zbirko podatkov.
Kakovost kode
composer cs # PSR-12 coding standards check
composer cs:fix # Auto-fix coding standards
composer analyse # PHPStan level 10 static analysis
Kategorije scenarijev
čisti (8 scenarijev)
Čista združevanja brez sporov. Obe strani lahko spreminjata podatke, vendar nikoli istega stolpca v isti vrstici.
| Scenarij | Preizkuša |
|---|---|
insert-only-theirs |
Njihova kopija je vstavila vrstice, naša je nespremenjena. |
update-only-theirs |
Njihova kopija je posodobila vrstice, naša je nespremenjena. |
delete-only-theirs |
Njihova kopija je izbrisala vrstice, naša je nespremenjena. |
insert-only-ours |
Naša kopija je vstavila vrstice, njihova je nespremenjena. |
mixed-no-overlap |
Obe strani sta spremenili različne tabele ali vrstice. |
both-same-change |
Obe strani sta izvedli enake spremembe (brez spora). |
column-level-clean |
Obe strani sta spremenili isto vrstico, vendar različne stolpce. |
multi-table |
Spremembe v več tabelah. |
spori (6 scenarijev)
Scenariji, pri katerih mora priti do sporov.
| Scenarij | Preizkuša |
|---|---|
both-update-same-column |
Obe strani sta isti stolpec spremenili na različni vrednosti. |
update-vs-delete |
Ena stran je posodobila, druga pa izbrisala isto vrstico. |
delete-vs-update |
Obratna smer posodobitve v primerjavi z izbrisom. |
both-insert-same-pk |
Obe strani sta vstavili vrstico z istim primarnim ključem. |
multiple-conflicts |
Več sporov v enem združevanju. |
partial-conflict |
Nekateri stolpci so v sporu, drugi se združijo brez težav. |
identiteta (4 scenariji)
Robni primeri identitete vrstic.
| Scenarij | Preizkuša |
|---|---|
auto-increment |
Nove vrstice imajo med vejami različne ID-je. |
natural-key |
Ujemanje po enoličnih stolpcih namesto po primarnem ključu. |
composite-key |
Večstolpčni primarni ključ. |
no-key |
Tabela brez primarnega ključa (nadomestno ujemanje zgoščene vsebine). |
tipi (6 scenarijev)
Obravnava podatkovnih tipov pri vseh tipih stolpcev.
| Scenarij | Preizkuša |
|---|---|
text-columns |
Vrednosti VARCHAR, TEXT in LONGTEXT. |
numeric-columns |
Vrednosti INT, DECIMAL in FLOAT. |
date-columns |
Vrednosti DATE, DATETIME in TIMESTAMP. |
json-columns |
Združevanje stolpca JSON. |
blob-columns |
Binarni podatki. |
null-handling |
Prehodi iz NULL v vrednost in iz vrednosti v NULL. |
obseg (4 scenariji)
Zmogljivost pri obremenitvi.
| Scenarij | Preizkuša |
|---|---|
1k-rows |
1,000 vrstic. |
10k-rows |
10,000 vrstic. |
100k-rows |
100,000 vrstic. |
wide-table |
Tabelo s 50+ stolpci. |
robni primeri (4 scenariji)
Robni primeri in mejni pogoji.
| Scenarij | Preizkuša |
|---|---|
empty-changeset |
Brez sprememb na eni ali obeh straneh. |
schema-mismatch |
Stolpec, dodan ali odstranjen med posnetki. |
encoding |
UTF-8, emodžiji, posebni znaki. |
large-text |
Zelo velike vrednosti TEXT/LONGTEXT. |
Struktura scenarija
Vsak scenarij je imenik pod scenarios/<category>/<name>/ s konfiguracijo scenario.json:
{
"name": "column-level-clean",
"category": "clean",
"description": "Both sides modify same row but different columns",
"tables": ["test_posts"],
"expectations": {
"conflicts": 0,
"operations": 3,
"changeset_match": "exact",
"merge_match": "exact",
"sql_match": "semantic"
}
}
Pri scenarijih s spori so pričakovani spori podrobno določeni:
{
"expectations": {
"conflicts": 1,
"conflict_details": [
{
"table": "test_posts",
"primary_key": {"id": 42},
"column": "title",
"ours_value": "Welcome",
"theirs_value": "Greetings"
}
]
}
}
Postopek ScenarioRunner
ScenarioRunner::run() usklajuje en sam scenarij:
OracleCapture::compute()iz podatkov JSON scenarija ustvari tri posnetke in izvede združevanje.ScenarioComparator::compare()preveri rezultat združevanja glede na pričakovane vrednosti vscenario.json.- Vrne rezultat uspeh/neuspeh in seznam sporočil o napakah.
use Merql\Tests\Oracle\ScenarioRunner;
$result = ScenarioRunner::run($scenario);
// ['name' => 'column-level-clean', 'pass' => true, 'failures' => []]
ScenarioRunner::runAll() zaporedno zažene vsak scenarij:
$results = ScenarioRunner::runAll($scenarios);
Dodajanje novega scenarija
- Ustvarite imenik:
scenarios/<category>/<name>/. - Ustvarite
scenario.jsonz metapodatki scenarija in pričakovanji. - V konfiguraciji JSON določite tri stanja zbirke podatkov: osnovne podatke, spremembe v naši kopiji in spremembe v njihovi kopiji.
- Zaženite scenarij:
./bin/test-scenario <name>. - Preverite celotno zbirko:
./bin/verify-all.
Standardi kakovosti kode
merql uveljavlja:
- PHPStan stopnje 10 -- strogo statično analizo brez izjem na podlagi osnovne konfiguracije.
- PSR-12 -- standarde kodiranja preverja
phpcs. - Regresijski preizkus na podlagi referenčnih rezultatov -- vseh 32 scenarijev mora uspeti.
- Enotski testi -- izolirani testi za vsako komponento.
Skript verify-all zaporedno izvede vsa štiri preverjanja. Delna potrditev ni sprejemljiva.
Neprekinjena integracija
CI ob vsakem potisku in zahtevku za združitev v main izvede preverjanje standardov kodiranja, PHPStan, composer test, integracijsko zbirko za MySQL 8.4 prek mysqli, preverjanje primitivov za združevanje in composer audit. Ne zažene regresijskega korpusa referenčnih testov (#6), zato pred zaupanjem v spremembo lokalno zaženite composer test:oracle ali ./bin/verify-all.