Katakanlah saya mulai mengembangkan permainan peran dengan karakter yang menyerang karakter lain dan hal-hal semacam itu.
Menerapkan TDD, saya membuat beberapa test case untuk menguji logika di dalam Character.receiveAttack(Int)
metode. Sesuatu seperti ini:
@Test
fun healthIsReducedWhenCharacterIsAttacked() {
val c = Character(100) //arg is the health
c.receiveAttack(50) //arg is the suffered attack damage
assertThat(c.health, is(50));
}
Katakanlah saya punya 10 metode metode pengujian receiveAttack
. Sekarang, saya menambahkan metode Character.attack(Character)
(yang memanggil receiveAttack
metode), dan setelah beberapa siklus TDD mengujinya, saya membuat keputusan: Character.receiveAttack(Int)
seharusnya private
.
Apa yang terjadi dengan 10 kasus uji sebelumnya? Haruskah saya menghapusnya? Haruskah saya menjaga metode public
(saya tidak berpikir begitu)?
Pertanyaan ini bukan tentang bagaimana menguji metode pribadi tetapi bagaimana menghadapinya setelah desain ulang ketika menerapkan TDD
sumber
internal
atau setara dengan bahasa Anda untuk tetap mencegahnya diekspos. Sebenarnya jawaban Kevin Cline adalah pendekatan semacam ini.Jawaban:
Di TDD, tes berfungsi sebagai dokumentasi yang dapat dieksekusi dari desain Anda. Desain Anda berubah, jadi jelas, dokumentasi Anda juga harus!
Perhatikan bahwa, dalam TDD, satu-satunya cara
attack
metode ini dapat muncul, adalah sebagai hasil dari gagal lulus ujian. Yang berarti,attack
sedang diuji oleh beberapa tes lain. Yang berarti secara tidak langsungreceiveAttack
ditanggung olehattack
tes. Idealnya, setiap perubahanreceiveAttack
harus mematahkan setidaknya satu dariattack
tes.Dan jika tidak, maka ada fungsi
receiveAttack
yang tidak lagi diperlukan dan seharusnya tidak ada lagi!Jadi, karena
receiveAttack
sudah diuji cobaattack
, tidak masalah apakah Anda menyimpan tes Anda atau tidak. Jika kerangka pengujian Anda membuatnya mudah untuk menguji metode pribadi, dan jika Anda memutuskan untuk menguji metode pribadi, maka Anda dapat menyimpannya. Tetapi Anda juga dapat menghapusnya tanpa kehilangan cakupan tes dan kepercayaan diri.sumber
Jika metode ini cukup kompleks sehingga perlu pengujian, itu harus umum di beberapa kelas. Jadi, Anda refactor dari:
untuk:
Pindahkan tes saat ini untuk X.complexity ke ComplexityTest. Kemudian teks X.sesuatu dengan mengejek Kompleksitas.
Dalam pengalaman saya, refactoring menuju kelas yang lebih kecil dan metode yang lebih pendek memberikan manfaat besar. Mereka lebih mudah dipahami, lebih mudah untuk diuji, dan akhirnya digunakan kembali lebih dari yang mungkin diharapkan.
sumber
this.health = this.health - attackDamage
). Mungkin mengekstraknya ke kelas lain adalah solusi overengineered, untuk saat ini.Yang perlu diingat di sini adalah bahwa keputusan yang Anda buat adalah menghapus metode dari API . Saran dari kompatibilitas mundur akan menyarankan
Tes dihapus / atau diganti ketika API Anda tidak lagi mendukung metode ini. Pada titik itu, metode pribadi adalah detail implementasi yang Anda harus dapat refactor pergi.
Pada titik itu, Anda kembali ke pertanyaan standar tentang apakah rangkaian pengujian Anda harus secara langsung mengakses implementasi, lebih tepatnya berinteraksi murni melalui API publik. Metode pribadi adalah sesuatu yang harus bisa kita ganti tanpa test suite menghalangi . Jadi saya akan mengharapkan pasangan tes untuk pergi - baik mendapatkan pensiun, atau bergerak dengan implementasi ke komponen yang dapat diuji secara terpisah.
sumber