Preskoči na vsebino

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.

Lupina
# 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:

  1. Priprava -- ustvarite tri stanja zbirke podatkov (osnovno stanje, naša kopija, njihova kopija) z znano vsebino.
  2. Referenčni rezultat -- iz znanih vhodnih podatkov izračunajte pričakovani rezultat združevanja.
  3. Dejanski rezultat -- izvedite združevanje treh stanj z merql.
  4. Primerjava -- dejanski rezultat se mora natančno ujemati s pričakovanim.
Koda
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:

Lupina
./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:

Lupina
./bin/test-regression

Zaženite eno kategorijo:

Lupina
./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):

Lupina
./bin/test-regression --fast

Posamezen scenarij

Preizkusite en scenarij skozi celoten postopek:

Lupina
./bin/test-scenario column-level-clean

Posamezni koraki referenčnega preizkusa

Lupina
./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

Lupina
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

Lupina
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:

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:

JSON
{
    "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:

  1. OracleCapture::compute() iz podatkov JSON scenarija ustvari tri posnetke in izvede združevanje.
  2. ScenarioComparator::compare() preveri rezultat združevanja glede na pričakovane vrednosti v scenario.json.
  3. Vrne rezultat uspeh/neuspeh in seznam sporočil o napakah.
PHP
use Merql\Tests\Oracle\ScenarioRunner;

$result = ScenarioRunner::run($scenario);
// ['name' => 'column-level-clean', 'pass' => true, 'failures' => []]

ScenarioRunner::runAll() zaporedno zažene vsak scenarij:

PHP
$results = ScenarioRunner::runAll($scenarios);

Dodajanje novega scenarija

  1. Ustvarite imenik: scenarios/<category>/<name>/.
  2. Ustvarite scenario.json z metapodatki scenarija in pričakovanji.
  3. V konfiguraciji JSON določite tri stanja zbirke podatkov: osnovne podatke, spremembe v naši kopiji in spremembe v njihovi kopiji.
  4. Zaženite scenarij: ./bin/test-scenario <name>.
  5. 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.