Standar pengkodean unit test

22

Biasanya ketika berbicara tentang standar pengkodean kita merujuk ke kode program itu sendiri, tetapi bagaimana dengan tes unit? Apakah ada pedoman standar pengkodean tertentu yang unik untuk pengujian unit? Apakah mereka?

EpsilonVector
sumber

Jawaban:

12

Dari atas kepala saya, saya bisa memikirkan tiga perbedaan dalam gaya pengkodean untuk kode uji.

Dalam penamaan metode pengujian, saya mengikuti pola shouldDoSomethingWhenSomeConditionHolds.

Di dalam tes, biasanya mengikuti pola penspasian berikut:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

Beberapa bersikeras hanya satu pernyataan per tes, tetapi ini jauh dari universal.

KERING (Jangan Ulangi Diri Sendiri) kurang mempertimbangkan kode uji daripada kode produksi. Sementara beberapa kode berulang harus ditempatkan dalam metode setUp atau kelas testUtils, berusaha keras untuk tidak mengulangi kode uji akan mengarah pada tes yang digabungkan secara ketat dan tidak fleksibel, yang menghambat refactoring.

Eric Wilson
sumber
Tentu saja, ada berbagai pola, itulah sebabnya Anda harus memberikan jawaban juga.
Eric Wilson
10
Itulah pola Arrange, Act, Assert .
StuperUser
KERING masih penting. Jika Anda perlu melakukan penegasan yang sama dalam beberapa pengujian, buat fungsi umum dan panggil di semua pengujian.
MiFreidgeim, berhentilah berbuat jahat
@MichaelFreidgeim Mungkin kita hanya berbicara tentang derajat, tetapi saya memiliki toleransi yang jauh lebih tinggi untuk pengulangan dalam kode uji. Saya telah memiliki beberapa pengalaman membangun suite tes dengan pengulangan yang sangat sedikit, dan menemukan bahwa tes menjadi sulit untuk dimodifikasi dan dipahami ketika persyaratan berubah. Kemudian saya berhenti mengkhawatirkan tentang DRY dalam tes, dan suite tes saya lebih mudah digunakan. <shrug>
Eric Wilson
16

Roy Osherove merekomendasikan pola berikut untuk menamai tes Anda:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

Lihat http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx

Robert Harvey
sumber
Saya setuju dengan Roy. Itu meningkatkan keterbacaan, meskipun ReSharper terus mengatakan kepada saya bahwa saya harus menghapusnya NameOfMethodUnderTestStateUnderTestExpectedBehavior();)
Oscar Mederos
Bagaimana cara membuat ini berfungsi ketika metode kelebihan beban, sehingga bisa ada beberapa metode dengan nama yang sama?
Narendra Pathai
6

Yang utama adalah untuk mengingat bahwa unit test pada dasarnya adalah spesifikasi-mini. Ini berarti bahwa penekanannya harus selalu pada keterbacaan.

Pertama, ini berarti bahwa nama-nama harus dengan jelas mengomunikasikan apa yang sedang diuji dan apa yang ditegaskan.

Kedua, yang kadang-kadang dilupakan, adalah bahwa sebagai spesifikasi mereka harus melakukan hal itu - menentukan perilaku. Artinya, tes unit tidak boleh mengandung logika - atau berpotensi jatuh ke dalam perangkap mengulangi fungsionalitas program daripada mengujinya.

Terkadang tes akan melibatkan objek yang rumit untuk diatur, Anda harus berusaha untuk menjaga logika pengaturan ini terpisah dari tes Anda menggunakan sesuatu seperti ibu objek atau pembangun data uji .

Saya hanya akan melengkapi dengan beberapa rekomendasi buku:

xUnit Test Patterns: Refactoring Test Code: Buku yang bagus, ada yang bilang agak kering tapi saya rasa tidak. Berikan banyak detail tentang berbagai cara pengorganisasian tes dan cara mempertahankannya. Relevan jika Anda menggunakan sesuatu seperti NUnit dll.

Seni Pengujian Unit: Dengan Contoh di .Net : Buku terbaik tentang seluk beluk penulisan dan pemeliharaan tes. Meskipun benar-benar baru saya menemukan bagian mengejek sedikit tanggal sudah sebagai sintaks AAA sekarang cukup standar daripada hanya cara lain untuk melakukannya.

Perangkat Lunak Tumbuh Berorientasi Objek, Dipandu oleh Tes : Buku ini sangat menakjubkan! Sejauh ini buku pengujian unit terbaik dan satu-satunya yang canggih yang menempatkan pengujian unit sebagai warga negara kelas satu dalam proses desain. Sedang membaca ini ketika itu adalah beta publik dan telah merekomendasikan sejak. Contoh karya dunia nyata yang sangat baik digunakan di seluruh buku Akan merekomendasikan membaca buku Roy terlebih dahulu.

FinnNk
sumber
IMHO tidak apa-apa untuk pengujian unit mengandung logika: Sangat masuk akal untuk menguji versi algoritma yang sangat optimal dan efisien dengan menggunakan algoritma naif yang melakukan hal yang sama untuk menentukan perilaku yang benar. Misalnya, bayangkan menguji tabel hash dengan membangun array asosiatif berbasis pencarian linier.
dsimcha
2
Ya, tapi itu termasuk di luar tes dalam pembangun data uji (yang harus diuji sendiri jika logika di dalamnya tidak sepele). Pengecualian untuk ini adalah perpustakaan pihak ke-3 yang umumnya "tepercaya" untuk menjadi benar dan dapat digunakan tanpa tes.
FinnNk
3

Jangan masukkan logika pada unit test Anda. Misalnya, katakanlah Anda sedang menguji metode add, Anda dapat memiliki sesuatu seperti ini:

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

Dalam kasus khusus ini, Anda cenderung mengulangi logika yang sama dengan apa yang ada dalam pengujian, jadi Anda pada dasarnya menguji "1 + 1 == 1 + 1", daripada "1 + 1 == 2", yang merupakan tes "nyata". Jadi yang Anda inginkan dari kode tes Anda adalah:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}
Hugo
sumber
2
Koreksi kecil: Saya pikir maksud Anda 'string expected = string.Format ("Hello, Bob")' harus 'string expected = "Hello, Bob"'.
Mike Rosenblum
@MikeRosenblum Anda jelas benar, dan seseorang mencoba memperbaikinya, tetapi dua pengulas menolak suntingan ini
Konrad Morawski
@ Konrad: itu aneh. Ini adalah forum pemrograman, bukan?
Mike Rosenblum
Saya sudah mengedit jawaban sekali lagi seperti yang disarankan oleh Mike Rosenblum.
bdsl
0

Nama metode deskriptif panjang. Ingat, metode pengujian tidak pernah dipanggil dari kode (mereka dipanggil oleh unit test runner yang menemukan dan memanggil mereka melalui refleksi), jadi tidak apa-apa untuk menjadi gila dan memiliki nama metode yang panjangnya 50-80 karakter. Konvensi penamaan khusus (kasus unta, garis bawah, "harus", "harus", "ketika", "diberikan", dll.) Tidak terlalu penting selama nama menjawab tiga pertanyaan:

  • apa yang sedang diuji?
  • apa kondisinya?
  • Apa hasil yang diharapkan?

Metode pengujian harus pendek .

Metode pengujian harus memiliki struktur linier sederhana . Tidak ada jika atau loop dikonstruksi.

Metode pengujian harus mengikuti pola "atur-atakan-tindakan" .

Setiap tes harus menguji satu hal . Ini biasanya berarti satu pernyataan per tes. Tes seperti { Do A; Assert B; Assert C; }harus direstorasi menjadi dua: { Do A; Assert B; }dan{ Do A; Assert C; }

Hindari data acak atau hal-hal seperti 'DateTime.Now'

Pastikan bahwa semua anggota perlengkapan tes dikembalikan ke keadaan semula di akhir tes (mis. Menggunakan teardown )

Bahkan jika Anda menghapus duplikasi tanpa ampun dalam kode produksi Anda, duplikasi kode dalam perlengkapan pengujian adalah masalah yang jauh lebih kecil.

azheglov
sumber
-1

Agak mirip dengan apa yang Farmboy sebutkan, Format nama metode saya

 <MethodName>Should<actionPerformed>When<Condition>

misalnya

 GetBalanceShouldReturnAccountBalance() {
Amit Wadhwa
sumber