Model sumber pengujian unit

10

Saya memiliki beberapa model dalam ekstensi khusus saya yang hanya melayani keperluan mengisi beberapa pilihan dan / atau multiseleksi dalam bentuk tambah / edit entitas saya.
Jadi itulah yang disebut Magento "model sumber".
Nilai yang terlibat selalu sama dan metode mengembalikan hal yang sama.
Bagaimana saya harus menguji unit-unit itu? Atau bahkan lebih baik, haruskah saya menulis tes unit untuk mereka?
Berikut ini sebuah contoh.
Kelas berikut ini digunakan untuk menambah / mengedit formulir untuk bidang yang dipanggil typedan untuk kolom kotak dari bidang yang sama.

<?php
namespace Sample\News\Model\Author\Source;

use Magento\Framework\Option\ArrayInterface;

class Type implements ArrayInterface
{
    const COLLABORATOR = 1;
    const EMPLOYEE = 2;

    /**
     * Get options
     *
     * @return array
     */
    public function toOptionArray()
    {
        $_options = [
            [
                'value' => '',
                'label' => ''
            ],
            [
                'value' => self::COLLABORATOR,
                'label' => __('Collaborator')
            ],
            [
                'value' => self::EMPLOYEE,
                'label' => __('Employee')
            ],
        ];
        return $_options;
    }

    /**
     * get options as key value pair
     *
     * @return array
     */
    public function getOptions()
    {
        $_tmpOptions = $this->toOptionArray();
        $_options = [];
        foreach ($_tmpOptions as $option) {
            $_options[$option['value']] = $option['label'];
        }
        return $_options;
    }
}
Marius
sumber

Jawaban:

15

Ini adalah utas yang bagus, dan saya sangat menyukai Jawaban dari @KAndy dan @fschmengler.
Saya ingin menambahkan beberapa pemikiran tambahan yang saya anggap berharga ketika mengajukan pertanyaan seperti "Haruskah saya menguji X?" atau "Bagaimana saya harus menguji X?".

Apa yang bisa salah?

  • Saya bisa membuat kesalahan ketik bodoh (terjadi sepanjang waktu)
    Ini biasanya tidak membenarkan menulis tes.
  • Apakah saya akan menyalin kode yang saya butuhkan dari inti atau modul yang berbeda, dan kemudian menyesuaikannya dengan kebutuhan saya?
    Saya menemukan ini sebenarnya hal yang sangat berbahaya untuk dilakukan yang sering meninggalkan bug halus. Dalam hal ini, saya lebih suka menulis tes, jika tidak terlalu mahal. Membuat konfigurasi model sumber berdasarkan sebenarnya akan membuat mereka lebih berisiko IMO.
  • Bisakah ada konflik dengan modul yang berbeda?
    Ini hampir hanya berlaku untuk kode konfigurasi. Dalam kasus seperti itu saya ingin memiliki tes integrasi yang memberi tahu saya ketika itu terjadi.
  • Bisakah Magento mengubah API dalam rilis yang akan datang?
    Sangat tidak mungkin dalam hal ini, karena kode Anda hanya bergantung pada antarmuka. Tetapi semakin banyak kelas konkret yang terlibat atau jika kode saya memperluas kelas inti, ini menjadi risiko yang lebih potensial.
  • Versi PHP baru dapat memecahkan kode saya. Atau mungkin saya ingin mendukung PHP 5.6 untuk tahun-tahun mendatang.
    Sekali lagi, sangat tidak mungkin di sini, tetapi dalam beberapa kasus saya ingin tes memperingatkan saya, haruskah saya mengubah kode di masa depan untuk menggunakan sintaks yang tidak kompatibel.

Seberapa mahal untuk menguji kode?

Ini memiliki dua aspek:

  • Jumlah usaha dan waktu yang dibutuhkan untuk menulis ujian
  • Jumlah usaha dan waktu yang diperlukan untuk menguji potongan kode yang akan saya tulis secara manual.

Selama pengembangan beberapa kode, saya cenderung harus menjalankan kode yang saya tulis cukup sering sampai saya menganggapnya selesai. Ini tentu saja jauh lebih mudah dengan uji unit.

Dalam kasus Anda, menulis ujian sangat murah. Tidak butuh banyak waktu atau usaha. @KAndy benar bahwa semua kode perlu dipertahankan, tetapi sekali lagi, tidak semua tes perlu disimpan.
Ini mungkin contoh di mana saya akan menulis unit test, hanya untuk memeriksa saya tidak membuat kesalahan bodoh, dan kemudian menghapusnya setelah kelas selesai. Jika tes tidak memberikan nilai jangka panjang, saya pikir menghapusnya masuk akal.

Pertanyaan ini juga penting dalam hal memilih jenis tes untuk ditulis: unit atau integrasi misalnya.

Seberapa berharganya potongan kode yang saya tulis?

Jika sepotong kode yang saya tulis sangat penting untuk layanan yang disediakan modul, saya mengujinya, terlepas dari seberapa sepele itu.
Jika itu hanya metode utilitas kecil, misalnya UI fokus, dan bukan bagian dari logika bisnis, maka mungkin tidak.

Apakah kode perlu diubah?

Seiring waktu, saya menjadi sangat terbiasa memiliki cakupan pengujian, sehingga mengubah kode yang terbuka terasa sangat tidak aman. Itu termasuk hal-hal yang sangat sederhana seperti menambahkan opsi ke model sumber, tetapi juga hal-hal seperti memindahkan kelas ke folder / namespace yang berbeda, atau mengubah nama metode.
Memiliki tes untuk perubahan tersebut sangat berharga.

Apakah perlu dokumentasi?

Seberapa sulit untuk menggunakan kode? Dalam contoh Anda itu sepele, tetapi dalam beberapa kasus yang lebih kompleks, melakukan tes sangat bagus untuk keperluan dokumentasi untuk pengembang lain (atau saya sendiri dalam beberapa bulan).

Eksplorasi dan Pembelajaran

Jika saya mengerjakan beberapa kode dan saya tidak yakin cara mengujinya, saya merasa sangat berharga untuk menulis tes. Prosesnya hampir selalu memberi saya pemahaman yang lebih dalam tentang apa yang saya hadapi.
Ini terutama berlaku untuk pengembang yang masih menganggap diri mereka sedang belajar pengujian.
Ini juga merupakan contoh di mana mungkin masuk akal untuk menghapus tes setelahnya, karena nilai utama yang diberikannya adalah belajar.

Disiplin dan Stres

Menempel pada loop merah-hijau-refactor membantu saya untuk bergerak cepat. Ini terutama benar di bawah tekanan. Jadi, bahkan jika beberapa bagian kode tidak benar-benar layak uji, saya mungkin masih mengikuti TDD, terutama jika kode itu sepele untuk diuji.
Ini membuat saya dalam arus dan waspada.

Apa dan bagaimana cara menguji?

Juga pertimbangkan Anda dapat menulis tes dalam rincian yang sangat berbeda.

  • Menguji nilai pengembalian tepat.
    Ini akan menjadi tes yang sangat kaku yang harus disesuaikan dengan setiap perubahan. Apakah Anda ingin tes untuk istirahat, misalnya, jika urutan item dalam array kembali berubah?
  • Menguji struktur nilai pengembalian.
    Untuk model sumber ini bisa memeriksa setiap sub-array sebagai dua catatan, satu dengan a labeldan satu dengan valuekunci.
  • Memeriksa implementasi kelas ArrayInterface.
  • Menguji kelas menyediakan getOptions()meskipun metode itu bukan bagian dari antarmuka yang diimplementasikan.

Untuk setiap hal yang mungkin dapat diuji, pertimbangkan nilai, rawatan, dan biaya.

Ringkasan

Singkatnya: tidak ada jawaban tunggal sejati untuk sebuah pertanyaan jika beberapa kode harus diuji atau tidak. Jawabannya akan berbeda untuk setiap pengembang tergantung pada keadaan.

Vinai
sumber
2
Jawaban bagus! Saya ingin menyoroti bagian "hapus pengujian saat tidak lagi memberikan nilai" - terkadang pengujian lama yang membantu selama pengembangan awal, hanya menghambat jangka panjang.
Fabian Schmengler
1
Anda baru saja menjawab 2 pertanyaan lain yang saya ragukan. terima kasih
Marius
6

Menurut pendapat saya, tidak ada jawaban umum untuk "tulis unit test untuk model sumber, ya atau tidak"

Saya telah menulis unit test untuk model sumber, tetapi itu adalah model sumber dinamis yang mengambil data eksternal dan itu masuk akal.

Untuk model sumber yang tidak lebih dari array yang dimuliakan (seperti pada contoh Anda), saya tidak akan repot menulis unit test. Namun dalam beberapa hal, Anda perlu memastikan Anda tidak melakukan kesalahan. Ada beberapa opsi:

  1. unit test
  2. tes integrasi
  3. secara manual melihat konfigurasi

Apakah Anda mengikuti TDD? Kemudian pilih antara (1) dan (2), atau keduanya. Jika tidak, pilih antara (2) dan (3).


Jika Anda menggunakan model sumber untuk opsi konfigurasi sistem, tes integrasi (satu tes untuk semua opsi konfigurasi Anda) dapat membuat bagian konfigurasi dan memeriksa apakah <select>elemen ada dan berisi nilai yang diharapkan. Ingat bahwa ini bukan tentang menguji satu kelas tertentu tetapi menguji bahwa semuanya terkait dengan benar.


Dan seperti yang dikatakan @KAndy, idealnya Anda tidak perlu pelat lantai yang banyak itu, cukup rentangkan kelas dasar yang sudah diuji unit dan timpa properti atau tentukan nilai dalam konfigurasi eksternal.

Dalam skenario itu, tes unit untuk implementasi konkret tidak memberikan nilai tambahan. Jika Anda memiliki banyak dari kelas-kelas ini, mungkin ide yang baik untuk menulis ArraySourcesendiri kelas dasar , selama Magento tidak menyediakannya.


Dengan kelas dasar seperti itu, model sumber Anda bisa terlihat seperti ini:

class Type extends ArraySource
{
    const COLLABORATOR = 1;
    const EMPLOYEE = 2;
    protected $elements = [
        self::COLLABORATOR => 'Collaborator',
        self::EMPLOYEE     => 'Employee',
    ];
    protected $withEmpty = true;
    protected $translate = true;
}
Fabian Schmengler
sumber
Terima kasih atas konfirmasinya. Saya akan mencoba mengubah array yang dimuliakan saya menjadi daftar opsi yang dapat dikonfigurasi, tetapi apakah hal yang sama berlaku untuk model yang akan memiliki opsi N persis? Seperti model sumber "status".
Marius
Saya tidak melihat bagaimana model sumber "status" akan berbeda dengan contoh "jenis penulis" Anda
Fabian Schmengler
karena saya mungkin menggunakan nilai 0 dan 1 (sebagai konstanta kelas) di frontend, untuk memfilter misalnya entitas yang diaktifkan. Maksud saya dalam hal ini, nilai opsi memiliki logika di belakangnya. mereka bukan hanya key=>valuepasangan.
Marius
Tetapi logika ini bukan bagian dari model sumber, bukan? Itu berarti tidak masalah di sini. Anda masih memiliki konstanta untuk digunakan di tempat lain. Saya menambahkan contoh bagaimana saya akan menggunakan implentasi seperti itu.
Fabian Schmengler
5

Bagaimana saya harus menguji unit-unit itu?

Saya pikir Anda seharusnya tidak.

Tambahkan kode ke dukungan peningkatan sistem dan biaya pemeliharaan tetapi proses pengujian harus LEAN .

Lebih dari kode ini seharusnya tidak ada. Saya percaya daripada di Magento harus menjadi salah satu cara deklaratif umum untuk mendefinisikan set opsi untuk digunakan di tempat yang berbeda. Dan keengganan Anda menulis tes untuk kelas ini menunjukkan bau kode yang buruk

KAndy
sumber
1
Terima kasih. Jadi Anda mengatakan bahwa opsi-opsi ini tidak boleh berupa hard-coded tetapi berasal dari file konfigurasi (misalnya di.xml). Saya bisa melakukan itu. Tetapi apakah hal yang sama berlaku untuk model sumber status? Maksud saya, jika saya memiliki kelas yang sama seperti di atas tetapi hanya dengan status yang diaktifkan dan dinonaktifkan (1,0) haruskah saya menggunakan pendekatan konfigurasi yang sama? Jika ya, saya ingin mengatakan bahwa itu seperti over-engineering untuk saya.
Marius