Lewati ke konten

Strategi Pengujian

merql menggunakan model pengujian berbasis oracle. Setiap skenario pengujian menentukan sekumpulan input yang diketahui (tiga keadaan basis data), hasil yang diharapkan secara deterministik (oracle), lalu membandingkan keluaran merge aktual dengan hasil tersebut. Ada 32 skenario yang mencakup merge tanpa konflik, konflik, resolusi identitas, tipe data, skala, dan kasus tepi.

Shell
# Run the full verification suite.
./bin/verify-all

Perintah di halaman ini dijalankan dari checkout repositori merql setelah composer install. Skrip pengembangan di bin/, korpus scenarios/, dan pengujian bukan bagian dari paket Composer. Dependensi pengembangan mencakup PHPUnit 13, yang memerlukan PHP 8.4 atau lebih baru, meskipun pustaka itu sendiri berjalan pada PHP 8.2.

Pengujian berbasis oracle

Tidak ada alat referensi yang tersedia untuk melakukan merge basis data tiga arah, jadi oracle dihitung dari input yang diketahui, bukan dibuat oleh alat eksternal. Setiap skenario memiliki hasil yang diharapkan secara deterministik dan dapat diverifikasi secara logis:

  1. Penyiapan -- buat tiga keadaan basis data (base, sisi kita, sisi mereka) dengan konten yang diketahui.
  2. Oracle -- hitung hasil merge yang diharapkan dari input yang diketahui.
  3. Aktual -- jalankan merge merql pada ketiga keadaan.
  4. Bandingkan -- hasil aktual harus sama persis dengan hasil yang diharapkan.
Kode
Known inputs (base, ours, theirs)
         |                    |
    Deterministic          merql merge
    computation
         |                    |
    Expected result       Actual result
         |                    |
         -----> Compare <-----
                  |
            Pass or Fail

Menjalankan pengujian

Verifikasi lengkap

Skrip verify-all adalah pemeriksaan akhir. Skrip ini menjalankan analisis statis, standar pengodean, pengujian PHPUnit, dan rangkaian regresi oracle:

Shell
./bin/verify-all

Semua pemeriksaan ini harus lolos sebelum pekerjaan dinyatakan selesai.

Rangkaian regresi oracle

Jalankan semua 32 skenario:

Shell
./bin/test-regression

Jalankan satu kategori:

Shell
./bin/test-regression --category clean
./bin/test-regression --category conflict
./bin/test-regression --category identity

Kategori adalah nama direktori di bawah scenarios/: clean, conflict, identity, types, scale, dan edge. Kategori yang tidak dikenal akan menampilkan No scenarios found dan keluar dengan sukses. --category dapat diulang untuk menjalankan beberapa kategori.

Skrip juga menerima --jobs, tetapi mengabaikan nilainya dan menjalankan skenario secara berurutan (#5).

Jalankan dengan keluaran minimal (hanya lulus/gagal):

Shell
./bin/test-regression --fast

Satu skenario

Uji satu skenario melalui seluruh alur:

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

Langkah oracle satu per satu

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

Pengujian unit

Shell
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 hanya menjalankan PHPUnit. Rangkaian oracle PHPUnit mengarah ke tests/Oracle, yang berisi kelas pelaksana skenario tetapi tidak memiliki kasus pengujian, jadi 32 skenario hanya dijalankan melalui composer test:oracle, composer verify, atau ./bin/verify-all.

Pengujian integrasi MySQL dilewati kecuali MERQL_MYSQL_HOST, MERQL_MYSQL_DATABASE, dan MERQL_MYSQL_USER (serta secara opsional MERQL_MYSQL_PASSWORD dan MERQL_MYSQL_PORT) mengarah ke basis data pengujian.

Kualitas kode

Shell
composer cs            # PSR-12 coding standards check
composer cs:fix        # Auto-fix coding standards
composer analyse       # PHPStan level 10 static analysis

Kategori skenario

clean (8 skenario)

Merge tanpa konflik. Kedua sisi dapat mengubah data, tetapi tidak pernah kolom yang sama pada baris yang sama.

Skenario Pengujian
insert-only-theirs Sisi mereka menyisipkan baris, sisi kita tidak berubah.
update-only-theirs Sisi mereka memperbarui baris, sisi kita tidak berubah.
delete-only-theirs Sisi mereka menghapus baris, sisi kita tidak berubah.
insert-only-ours Sisi kita menyisipkan baris, sisi mereka tidak berubah.
mixed-no-overlap Kedua sisi mengubah tabel atau baris yang berbeda.
both-same-change Kedua sisi membuat perubahan identik (tanpa konflik).
column-level-clean Kedua sisi mengubah baris yang sama, tetapi kolom berbeda.
multi-table Perubahan pada beberapa tabel.

conflict (6 skenario)

Skenario yang harus menghasilkan konflik.

Skenario Pengujian
both-update-same-column Kedua sisi mengubah kolom yang sama menjadi nilai berbeda.
update-vs-delete Satu sisi memperbarui, sisi lain menghapus baris yang sama.
delete-vs-update Arah sebaliknya untuk pembaruan versus penghapusan.
both-insert-same-pk Kedua sisi menyisipkan baris dengan kunci utama yang sama.
multiple-conflicts Beberapa konflik dalam satu merge.
partial-conflict Beberapa kolom berkonflik, sementara lainnya berhasil di-merge tanpa konflik.

identity (4 skenario)

Kasus tepi identitas baris.

Skenario Pengujian
auto-increment Baris baru memiliki ID berbeda antar cabang.
natural-key Cocokkan berdasarkan kolom unik, bukan PK.
composite-key Kunci utama dengan beberapa kolom.
no-key Tabel tanpa kunci utama (fallback hash konten).

types (6 skenario)

Penanganan tipe data untuk semua tipe kolom.

Skenario Pengujian
text-columns Nilai VARCHAR, TEXT, LONGTEXT.
numeric-columns Nilai INT, DECIMAL, FLOAT.
date-columns Nilai DATE, DATETIME, TIMESTAMP.
json-columns Merge kolom JSON.
blob-columns Data biner.
null-handling Transisi dari NULL ke nilai, dan dari nilai ke NULL.

scale (4 skenario)

Performa saat beban tinggi.

Skenario Pengujian
1k-rows 1,000 baris.
10k-rows 10,000 baris.
100k-rows 100,000 baris.
wide-table Tabel dengan 50+ kolom.

edge (4 skenario)

Kasus tepi dan kondisi batas.

Skenario Pengujian
empty-changeset Tidak ada perubahan di satu atau kedua sisi.
schema-mismatch Kolom ditambahkan atau dihapus antar snapshot.
encoding UTF-8, emoji, karakter khusus.
large-text Nilai TEXT/LONGTEXT yang sangat besar.

Struktur skenario

Setiap skenario adalah direktori di bawah scenarios/<category>/<name>/ dengan konfigurasi 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"
    }
}

Untuk skenario konflik, konflik yang diharapkan ditentukan secara terperinci:

JSON
{
    "expectations": {
        "conflicts": 1,
        "conflict_details": [
            {
                "table": "test_posts",
                "primary_key": {"id": 42},
                "column": "title",
                "ours_value": "Welcome",
                "theirs_value": "Greetings"
            }
        ]
    }
}

Alur ScenarioRunner

ScenarioRunner::run() mengatur satu skenario:

  1. OracleCapture::compute() membuat tiga snapshot dari data JSON skenario, lalu menjalankan merge.
  2. ScenarioComparator::compare() memeriksa hasil merge berdasarkan nilai yang diharapkan di scenario.json.
  3. Mengembalikan status lulus/gagal beserta daftar pesan kegagalan.
PHP
use Merql\Tests\Oracle\ScenarioRunner;

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

ScenarioRunner::runAll() menjalankan setiap skenario secara berurutan:

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

Menambahkan skenario baru

  1. Buat direktori: scenarios/<category>/<name>/.
  2. Buat scenario.json dengan metadata dan ekspektasi skenario.
  3. Tentukan tiga keadaan basis data dalam konfigurasi JSON: data base, perubahan di sisi kita, dan perubahan di sisi mereka.
  4. Jalankan skenario: ./bin/test-scenario <name>.
  5. Verifikasi seluruh rangkaian: ./bin/verify-all.

Standar kualitas kode

merql menerapkan:

  • PHPStan level 10 -- analisis statis ketat tanpa pengecualian baseline.
  • PSR-12 -- standar pengodean yang diperiksa oleh phpcs.
  • Regresi oracle -- semua 32 skenario harus lulus.
  • Pengujian unit -- pengujian terisolasi untuk setiap komponen.

Skrip verify-all menjalankan keempat pemeriksaan secara berurutan. Persetujuan parsial tidak diterima.

Integrasi berkelanjutan

CI menjalankan pemeriksaan standar pengodean, PHPStan, composer test, rangkaian integrasi pada MySQL 8.4 melalui mysqli, cakupan merge primitif, dan composer audit pada setiap push dan pull request ke main. CI tidak menjalankan korpus regresi oracle (#6), jadi jalankan composer test:oracle atau ./bin/verify-all secara lokal sebelum mengandalkan suatu perubahan.