Apa cara yang baik untuk menyatakan bahwa dua array objek adalah sama, ketika urutan elemen-elemen dalam array tidak penting, atau bahkan dapat berubah?
php
unit-testing
phpunit
assert
koen
sumber
sumber
Jawaban:
Cara terbersih untuk melakukan ini adalah memperluas phpunit dengan metode penegasan baru. Tapi ini ide untuk cara yang lebih sederhana untuk saat ini. Kode belum diuji, harap verifikasi:
Di suatu tempat di aplikasi Anda:
Dalam tes Anda:
sumber
count(array_diff_assoc($b, $a))
juga.Anda dapat menggunakan metode assertEqualsCanonicalize yang ditambahkan di PHPUnit 7.5. Jika Anda membandingkan array menggunakan metode ini, array ini akan diurutkan oleh komparator array PHPUnit itu sendiri.
Contoh kode:
Dalam versi PHPUnit yang lebih lama, Anda dapat menggunakan param $ canonicalize dari metode assertEquals tanpa dokumen . Jika Anda melewatkan $ canonicalize = true , Anda akan mendapatkan efek yang sama:
Array kode sumber komparator pada versi terbaru dari PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
sumber
$delta = 0.0, $maxDepth = 10, $canonicalize = true
untuk melewatkan parameter ke dalam fungsi menyesatkan - PHP tidak mendukung argumen bernama. Apa yang sebenarnya dilakukan adalah mengatur ketiga variabel tersebut, lalu segera meneruskan nilainya ke fungsi. Ini akan menimbulkan masalah jika ketiga variabel tersebut sudah didefinisikan dalam lingkup lokal karena mereka akan ditimpa.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Saya bisa menggunakan 4 baris, bukan 1, tapi saya tidak melakukannya.$canonicalize
akan dihapus: github.com/sebastianbergmann/phpunit/issues/3342 danassertEqualsCanonicalizing()
akan menggantinya.Masalah saya adalah saya memiliki 2 array (kunci array tidak relevan untuk saya, hanya nilainya).
Misalnya saya ingin menguji apakah
memiliki konten yang sama (pesanan tidak relevan untuk saya) seperti
Jadi saya telah menggunakan array_diff .
Hasil akhir adalah (jika array sama, perbedaannya akan menghasilkan array kosong). Harap dicatat bahwa perbedaannya dihitung dua arah (Terima kasih @beret, @GordonM)
Untuk pesan kesalahan yang lebih terperinci (saat debugging), Anda juga dapat menguji seperti ini (terima kasih @ DenilsonSá):
Versi lama dengan bug di dalamnya:
$ this-> assertEmpty (array_diff ($ array2, $ array1));sumber
$array1
memiliki nilai lebih dari$array2
, maka ia mengembalikan array kosong meskipun nilai array tidak sama. Anda juga harus menguji, bahwa ukuran array sama, untuk memastikan.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
tidak akan mencetak array jika tidak kosong, yang merepotkan saat uji debugging. Saya sarankan menggunakan:,$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
karena ini akan mencetak pesan kesalahan yang paling berguna dengan minimum kode tambahan. Ini berfungsi karena A \ B = B \ A ⇔ A \ B dan B \ A kosong ⇔ A = BArray to string conversion
pesan ketika Anda mencoba untuk melemparkan array ke string. Cara untuk menyiasatinya adalah dengan menggunakanimplode
Satu kemungkinan lain:
sumber
assertEquals
pesanan tidak masalah.$this->assertSame($exp, $arr);
yang melakukan perbandingan serupa karena$this->assertEquals(json_encode($exp), json_encode($arr));
hanya perbedaannya adalah kita tidak harus menggunakan json_encodeMetode pembantu sederhana
Atau jika Anda memerlukan lebih banyak info debug ketika array tidak sama
sumber
Jika arraynya bisa diurutkan, saya akan mengurutkan keduanya sebelum memeriksa persamaan. Jika tidak, saya akan mengonversinya menjadi beberapa set dan membandingkannya.
sumber
Menggunakan array_diff () :
Atau dengan 2 menegaskan (lebih mudah dibaca):
sumber
Meskipun Anda tidak peduli dengan pesanan, mungkin lebih mudah untuk memperhitungkannya:
Mencoba:
sumber
Kami menggunakan metode pembungkus berikut dalam Tes kami:
sumber
Jika kuncinya sama tetapi rusak, ini harus menyelesaikannya.
Anda hanya perlu mendapatkan kunci dalam urutan yang sama dan membandingkan hasilnya.
sumber
Solusi yang diberikan tidak melakukan pekerjaan untuk saya karena saya ingin dapat menangani array multi-dimensi dan memiliki pesan yang jelas tentang apa yang berbeda antara dua array.
Inilah fungsi saya
Lalu untuk menggunakannya
sumber
Saya menulis beberapa kode sederhana untuk pertama mendapatkan semua kunci dari array multi-dimensi:
Kemudian untuk menguji bahwa mereka terstruktur sama terlepas dari urutan kunci:
HTH
sumber
Jika nilai hanya int atau string, dan tidak ada array level ganda ....
Mengapa tidak hanya menyortir array, mengubahnya menjadi string ...
... lalu bandingkan string:
sumber
Jika Anda ingin menguji hanya nilai-nilai array yang dapat Anda lakukan:
sumber
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Pilihan lain, seolah-olah Anda belum memiliki cukup, adalah untuk menggabungkan
assertArraySubset
dikombinasikan denganassertCount
untuk membuat pernyataan Anda. Jadi, kode Anda akan terlihat seperti itu.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
Dengan cara ini Anda dapat memesan secara independen tetapi tetap menegaskan bahwa semua elemen Anda ada.
sumber
assertArraySubset
urutan masalah indeks sehingga tidak akan berfungsi. yaitu diri :: assertArraySubset (['a'], ['b', 'a']) akan salah, karena[0 => 'a']
tidak ada di dalam[0 => 'b', 1 => 'a']
assertEquals
sudah mengatasinya jika kunci tidak dalam urutan yang sama. Saya baru saja mengujinya.