Saya telah menguji unit saya di kelas, sekarang bagaimana saya memulai dengan tes integrasi?

19

Saya telah menulis sebuah kelas yang mengelola penerima di daftar MailChimp, yang disebut MailChimpRecipient. Ini menggunakan kelas MCAPI, yang merupakan pembungkus API pihak ketiga.

http://apidocs.mailchimp.com/api/1.3/ http://apidocs.mailchimp.com/api/downloads/

Saya melewatkan objek MCAPI ke konstruktor objek MailChimpRecipient, jadi saya telah menulis unit test menggunakan PHPUnit yang menguji semua logika di kelas saya sendiri (saya tidak menguji kelas MCAPI). Saya memiliki cakupan kode 100% dan semua tes lulus. Ini dilakukan dengan mengejek dan mematikan objek MCAPI.

Langkah saya selanjutnya adalah menulis tes integrasi, juga menggunakan PHPUnit, di mana saya akan membuat fixture MailChimpRecipient menggunakan objek MCAPI nyata, yang diatur untuk menggunakan daftar MailChimp yang asli.

Saya telah menulis apa yang saya pikir merupakan tes integrasi, yang pada dasarnya menjalankan tes terhadap antarmuka publik objek, seperti:

public function testAddedRecipientCanBeFound()
{
    $emailAddress = '[email protected]';
    $forename = 'Fred';
    $surname = 'Smith';

    // First, delete the email address if it is already on the list
    $oldRecipient = $this->createRecipient();
    if($oldRecipient->find($emailAddress))
    {
        $oldRecipient->delete();
    }
    unset($oldRecipient);

    // Add the recipient using the test data
    $newRecipient = $this->createRecipient();
    $newRecipient->setForename($forename);
    $newRecipient->setSurname($surname);
    $newRecipient->setEmailAddress($emailAddress);
    $newRecipient->add();
    unset($newRecipient);

    // Assert that the recipient can be found using the same email address
    $this->assertTrue($this->_recipient->find($emailAddress));
}

Tes "integrasi" tidak menguji salah satu internal kelas - itu hanya memastikan bahwa diberikan objek MCAPI nyata, itu berperilaku seperti yang diiklankan.

Apakah ini benar? Apakah ini cara terbaik untuk menjalankan tes intergasi? Bagaimanapun, bagian dalam telah diuji dengan unit test. Apakah saya benar dalam berpikir bahwa tes integrasi ada untuk menguji apakah itu benar-benar berfungsi, sesuai dengan cara perilakunya diiklankan?

Untuk mengambil langkah lebih jauh, kelas MailChimpRecipient mengimplementasikan antarmuka, yang juga akan diimplementasikan oleh kelas lain. Idenya adalah menggunakan pabrik untuk mengirimkan berbagai jenis objek penerima milis ke kode saya, yang semuanya melakukan hal yang sama, walaupun menggunakan penyedia milis yang berbeda. Karena tes integrasi saya menguji antarmuka itu, bagaimana menggunakannya untuk semua kelas yang mengimplementasikan antarmuka? Kemudian, di masa depan, jika saya merancang kelas baru untuk digunakan secara bergantian, saya dapat menjalankan tes integrasi yang sama sebelum memasukkannya ke dalam proyek.

Apakah ini masuk akal? Tes unit menguji internal suatu objek, tes intergrasi memastikan bahwa itu berperilaku seperti yang diiklankan?

Lewis Bassett
sumber
4
Saya pikir Anda memiliki terlalu banyak logika dalam pengujian Anda. Anda menjalankan banyak kode sampai Anda menegaskan. Anda mungkin ingin menguji penghapusan penerima terlebih dahulu. Tetapi itu tidak menjawab pertanyaan Anda, hanya sebuah komentar.
hakre
1
Nah, Anda harus menggunakan setUpfungsi untuk membangun alasan untuk menjalankan tes Anda. Jika input tidak ditentukan, Anda tidak dapat benar-benar menguji. Masukan harus tepat, ketat dan selalu sama. Jika prasyarat tes tidak terpenuhi, lewati saja tes. Kemudian menganalisis mengapa lompatan dan jika Anda perlu menambahkan tes tambahan dan / atau setUptidak dilakukan dengan benar.
hakre
1
Juga jangan nilai-nilai tes hardcode di dalam tes itu sendiri mungkin tetapi membuat anggota kelas sehingga mereka dapat dibagikan di seluruh tes (dan diubah di tempat pusat) atau menggunakan DataProvider(itu adalah fungsi yang menawarkan input sebagai parameter untuk tes).
hakre
1
Masukkan arti dari semua fungsi yang Anda uji. Saat Anda menguji menambahkan penerima dan Anda ingin memastikan bahwa itu belum ada, Anda setidaknya harus menegaskan penghapusan jika itu masuk. Jika tidak, prasyarat pengujian Anda tidak dijamin dapat diuji.
hakre
1
+1 untuk pertanyaan yang bagus, tetapi juga memilih untuk bermigrasi ke Programmer. Tampaknya di situlah pertanyaan tentang strategi pengujian termasuk
GordonM

Jawaban:

17

Saat menguji kode Anda, Anda harus memperhatikan tiga bidang:

  • Pengujian skenario
  • Pengujian fungsional
  • Pengujian unit

Biasanya jumlah tes yang Anda miliki di setiap kategori akan memiliki bentuk piramida, yang berarti banyak tes unit di bagian bawah, beberapa tes fungsional di tengah, dan hanya beberapa tes skenario.

Dengan unit test Anda mengejek segala sesuatu yang digunakan kelas yang diuji dan Anda mengujinya dalam isolasi murni (inilah mengapa penting untuk memastikan bahwa di dalam kelas Anda Anda mengambil semua dependensi melalui injeksi sehingga mereka dapat diganti dengan tes).

Dengan pengujian unit Anda menguji semua kemungkinan, jadi tidak hanya 'jalan bahagia' tetapi juga semua kondisi kesalahan.

Jika Anda benar-benar yakin bahwa semua unit Anda bekerja dalam isolasi Anda menulis beberapa tes (tes fungsional) untuk memastikan unit juga bekerja ketika digabungkan. Kemudian Anda menulis tes skenario, yang menguji kabel antara semua modul fungsional.

Misalnya, Anda sedang menguji mobil.

Anda dapat merakit seluruh mobil dan sebagai pengemudi memeriksa setiap kondisi yang mungkin tetapi itu akan sangat sulit dilakukan.

Sebagai gantinya Anda akan menguji sebagian kecil mesin dengan semua kemungkinan (uji unit)

Kemudian Anda menguji seluruh mesin (terpisah dari mobil) yang akan menjadi tes fungsional.

Sebagai tes terakhir, Anda memasukkan kunci Anda, menyalakan mobil dan mengendarainya ke tempat parkir. Jika itu berfungsi maka Anda tahu bahwa semua bagian (baterai, bahan bakar, mesin, ..) terhubung dan sejak Anda mengujinya secara terpisah, Anda dapat yakin bahwa seluruh mobil berfungsi dengan benar.

Jadi, dalam kasus Anda, Anda menguji semua kondisi kesalahan dan jalur bahagia dalam pengujian unit Anda dan tahu Anda hanya perlu melakukan tes ujung ke ujung dengan 'komponen nyata' untuk memeriksa apakah kabel benar.

Beberapa poin lainnya,

  • Hindari logika kondisional dalam pengujian unit Anda. Jika Anda harus membersihkan, Anda menggunakan semacam negara global dan tes tiba-tiba dapat saling mempengaruhi.
  • Jangan tentukan data apa pun yang tidak relevan untuk pengujian. Jika saya akan mengubah nama depan, atau nama keluarga, akankah tes gagal? Mungkin bukan karena alamat emailnya yang penting tetapi karena Anda menyebutkannya secara eksplisit dalam pengujian Anda, saya tidak bisa memastikan. Coba lihat Pola Builder untuk membangun data pengujian Anda dan membuatnya eksplisit apa yang benar-benar penting.
Wouter de Kort
sumber
Terima kasih, itu menegaskan banyak dari apa yang saya pikirkan. Hanya untuk memperjelas - ini BUKAN unit test. Saya sudah menulis unit test, yang menguji objek dalam isolasi lengkap dan memiliki cakupan kode 100% dari objek. Ini dimaksudkan untuk menjadi tes integrasi, untuk memastikan itu berfungsi ketika saya menyuntikkan objek MCAPI nyata ke dalamnya. Saya hanya perlu menghapus semua penerima yang ditambahkan ke daftar - itu semua pembersihan, dan itu dilaksanakan untuk memastikan bahwa tidak ada tes yang mempengaruhi satu sama lain. Apa yang akan Anda sarankan sebagai gantinya?
1
Ya! Saya mengerti Anda sudah melakukan tes unit. Apakah objek MCAPI melacak penerima dan apakah itu pembersihan yang harus Anda lakukan? Jika ini adalah 'masalah' pihak ketiga, tidak ada yang dapat Anda lakukan dalam tes integrasi. Jika Anda tetap melacak daftar tersebut, Anda harus memastikan Anda menghindari data global (dan lajang) untuk memastikan tes tidak saling memengaruhi. Di dunia yang sempurna, membersihkan berbagai hal saat tes dimulai / selesai, menunjuk pada cacat desain tetapi di dunia nyata, Anda tidak selalu bisa menghindarinya.
Wouter de Kort
1
Saya akan menambahkan bahwa pengujian skenario mungkin bukan sesuatu yang cocok untuk PHPUnit. Yu mungkin ingin melihat beberapa alat yang dapat Anda jalankan di browser seperti Selenium, atau alat yang dapat mensimulasikan browser, seperti jMeter.
GordonM
Terima kasih kawan! Ada banyak hal yang harus dipelajari ketika menulis kode yang dapat diuji, tidak ada. Saya telah memesan sendiri salinan buku ini: amazon.co.uk/… . Semoga apa yang Anda semua katakan akan lebih masuk akal setelah saya membacanya. @Wouter, saya hanya menghapus penerima karena tes akan menyebabkan alamat email ditambahkan ke daftar. Saya menghapusnya sehingga daftar tidak terpengaruh oleh tes itu.
1
@LewisBassett Saya bukan pengembang Php tetapi pola xUnit Test ( amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 ) jelas merupakan bacaan yang bagus. Juga artikel di misko.hevery.com/code-reviewers-guide benar-benar menarik.
Wouter de Kort