TDD jarang digunakan dalam pengembangan game. Biasanya lebih mudah untuk menyewa tester daripada menyisihkan pengembang untuk menulis tes - ini menghemat sumber daya dan waktu. Oleh karena itu, setiap kesuksesan penggunaan TDD menjadi lebih menarik. Di bawah potongan, terjemahan materi, di mana teknik pengembangan ini digunakan untuk membuat pergerakan karakter dalam game ElemenTerra.

Test-driven development atau TDD (pengembangan melalui pengujian) adalah teknik pengembangan perangkat lunak di mana seluruh proses dibagi menjadi banyak siklus kecil. Tes unit ditulis, kemudian kode ditulis yang lulus tes ini, dan kemudian dilakukan refactoring. Dan algoritma ini berulang.
Dasar-dasar TDD
Misalkan kita menulis fungsi yang menambahkan dua angka. Dalam alur kerja normal, kami hanya akan menulisnya. Tetapi untuk menggunakan TDD, Anda harus mulai dengan membuat fungsi placeholder dan tes unit:
// Placeholder-, : int add(int a, int b){ return -1; } // Unit-, , add : void runTests(){ if (add(1, 1) is not equal to 2) throw error; if (add(2, 2) is not equal to 4) throw error; }
Pada awalnya, pengujian unit kami tidak akan berfungsi, karena fungsi placeholder mengembalikan -1 untuk setiap input. Sekarang kita dapat menjalankan
add dengan benar untuk mengembalikan
+ b . Tes akan berlalu. Ini mungkin tampak seperti solusi, tetapi ada beberapa keuntungan:
Jika kita keliru menulis
add sebagai
a - b , tes kita tidak akan berfungsi, dan kita akan segera belajar cara memperbaiki fungsinya. Tanpa tes, kami tidak dapat menangkap kesalahan ini dan melihat reaksi non-standar yang akan membutuhkan waktu untuk debug.
Kami dapat melanjutkan tes dan menjalankannya kapan saja saat menulis kode. Ini berarti bahwa jika programmer lain secara tidak sengaja
menambahkan perubahan, ia akan segera mengenali kesalahan - tes akan gagal lagi.
TDD di game dev
Ada dua masalah dengan TDD di game dev. Pertama, banyak fungsi game memiliki tujuan subjektif yang tidak dapat diukur. Dan kedua, sulit untuk menulis tes yang mencakup semua kemungkinan ruang dunia yang penuh dengan objek yang saling berinteraksi kompleks. Pengembang yang ingin gerakan karakter mereka "terlihat baik" atau simulasi fisik "tidak terlihat tersentak-sentak" akan merasa sulit untuk mengekspresikan metrik ini sebagai kondisi deterministik "lulus / tidak lulus".
Namun, teknik TDD berlaku untuk fitur yang kompleks dan subyektif - misalnya, pergerakan karakter. Dan di dalam permainan ElemenTerra kita berhasil.
Tes unit terhadap level debug
Sebelum mulai berlatih, saya ingin membedakan antara tes unit otomatis dan "level debug" tradisional. Membuat lokasi tersembunyi dengan kondisi buatan adalah hal biasa di gamedev. Ini memungkinkan para programmer dan QA untuk memonitor setiap kejadian.
Level debugging rahasia dalam The Legend of Zelda: The Wind WakerElemenTerra memiliki banyak level seperti itu: level penuh geometri bermasalah untuk karakter pemain, level dengan antarmuka pengguna khusus yang memicu status permainan tertentu dan lainnya.
Seperti halnya tes unit, level debugging ini dapat digunakan untuk mereproduksi dan mendiagnosis kesalahan. Tetapi dalam beberapa hal mereka berbeda:
Tes unit membagi sistem menjadi beberapa bagian dan mengevaluasi masing-masing secara individu, sementara level debugging melakukan tes dengan cara yang lebih holistik. Setelah menemukan kesalahan di tingkat debugging, pengembang mungkin masih perlu mencari titik kesalahan secara manual.
Tes unit otomatis dan harus setiap kali memberikan hasil deterministik, sementara banyak level debug "dikontrol" oleh pemain. Ini membuat perbedaan dalam sesi.
Tetapi ini tidak berarti bahwa unit test lebih baik daripada level debugging. Yang terakhir seringkali lebih praktis. Namun, pengujian unit bahkan dapat digunakan pada sistem yang secara tradisional tidak ada.
Selamat datang di neraka kelinci
Di ElemenTerra, pemain menggunakan kekuatan mistis alam untuk menyelamatkan makhluk yang terkena badai antariksa. Salah satu kekuatan tersebut adalah kemampuan untuk membuka jalan yang mengarahkan makhluk ke makanan dan tempat berlindung. Karena jalur ini adalah kisi dinamis yang dibuat oleh pemain, gerakan makhluk itu harus berurusan dengan kasus geometris yang tidak biasa dan medan kompleks yang sewenang-wenang.
Pergerakan karakter adalah salah satu sistem kompleks di mana "segala sesuatu memengaruhi segalanya." Jika Anda pernah melakukan ini, Anda tahu bahwa ketika menulis kode baru, sangat mudah untuk merusak fungsionalitas yang ada. Apakah Anda perlu kelinci untuk memanjat tepian kecil? Oke, tapi sekarang mereka bergerak-gerak, mendaki lereng. Apakah Anda ingin jalur kadal tidak berpotongan? Itu berhasil, tetapi sekarang perilaku khas mereka hancur.
Sebagai orang yang bertanggung jawab atas AI dan sebagian besar kode gameplay, saya tahu bahwa saya tidak punya waktu untuk kesalahan kejutan. Saya ingin segera melihat regresi, jadi pengembangan menggunakan TDD sepertinya pilihan yang baik bagi saya.
Langkah selanjutnya adalah pembuatan sistem di mana saya dapat dengan mudah mengidentifikasi setiap kasus gerakan dalam bentuk tes lulus / gagal disimulasikan:

"Kelinci neraka" ini terdiri dari 18 koridor yang terisolasi. Masing-masing dengan makhluk dan rutenya sendiri, dirancang untuk bergerak hanya jika fungsi gerakan tertentu berfungsi. Tes dianggap berhasil jika kelinci mampu bergerak untuk waktu yang lama tanpa terhenti. Kalau tidak, tidak berhasil. Perhatikan bahwa kami hanya menguji tubuh makhluk (bidak dalam istilah Unreal), bukan kecerdasan buatan. Di ElemenTerra, makhluk bisa makan, tidur, dan bereaksi terhadap dunia, tetapi dalam "kelinci neraka" satu-satunya instruksi mereka adalah berlari di antara dua titik.
Berikut ini beberapa contoh tes tersebut:
1, 2, 3: Gerakan bebas, hambatan statis, dan hambatan dinamis
8 dan 9: Lereng yang seragam dan medan yang kasar
10: Lantai yang hilang
13: Reproduksi bug di mana makhluk tanpa akhir berputar di sekitar target terdekat
14 dan 15: Kemampuan untuk menavigasi tepian datar dan kompleks
Mari kita bicara tentang persamaan dan perbedaan antara implementasi saya dan TDD "bersih".
Sistem saya mirip dengan TDD dalam hal ini:
- Saya mulai mengerjakan fungsi dengan membuat tes, dan kemudian menulis kode yang diperlukan untuk menjalankannya.
- Saya terus menjalankan tes lama, menambahkan fitur baru.
- Setiap tes mengukur tepat satu bagian sistem, yang memungkinkan saya menemukan masalah dengan cepat.
- Tes otomatis dan tidak memerlukan input pemain.
Dan berbeda dalam hal ini:
- Saat mengevaluasi tes, ada unsur subjektivitas. Sementara kesalahan nyata bergerak (karakter tidak mendapatkan dari A ke B) dapat dideteksi secara programatik. Misalnya, posisi miring, masalah sinkronisasi animasi dan gerakan berkedut memerlukan penilaian manusia.
- Tes tidak sepenuhnya deterministik. Faktor acak, seperti fluktuasi dalam frame rate, menyebabkan penyimpangan kecil. Tetapi secara umum, makhluk biasanya mengikuti jalur yang sama dan memiliki keberhasilan / kegagalan yang sama di antara sesi.
Keterbatasan
Menggunakan TDD untuk memindahkan makhluk ElemenTerra merupakan nilai tambah yang besar, tetapi pendekatan saya memiliki beberapa keterbatasan:
- Tes unit mengevaluasi setiap fitur gerakan secara individual, sehingga kesalahan dengan kombinasi beberapa fitur tidak dipertimbangkan. Kadang-kadang perlu untuk melengkapi unit test dengan level debugging tradisional.
- ElemenTerra memiliki empat jenis makhluk, tetapi tes hanya mengandung kelinci. Ini adalah fitur dari jadwal produksi kami (tiga jenis lainnya ditambahkan jauh kemudian dalam pengembangan). Untungnya, keempatnya memiliki mobilitas yang sama, tetapi tubuh besar Mossmork menyebabkan beberapa masalah. Lain kali, saya akan melakukan tes secara dinamis menelurkan spesies yang dipilih daripada menggunakan kelinci yang telah ditempatkan sebelumnya.
Mossmork ini membutuhkan ruang lebih dari kelinci.TDD adalah pilihan Anda?
Pengembang mungkin menghabiskan terlalu banyak upaya pada level unit test yang tidak akan pernah dihargai pemain. Saya tidak menyangkal hal itu, saya sendiri menerima banyak kesenangan dari menciptakan "kelinci neraka". Fungsi internal semacam itu dapat memakan waktu dan membahayakan tonggak yang lebih penting. Untuk mencegah hal ini terjadi, pelajari dengan seksama di mana dan kapan harus menggunakan tes unit. Di bawah ini saya telah menyoroti beberapa kriteria yang membenarkan TDD untuk pergerakan makhluk ElemenTerra.
1. Apakah akan memakan waktu lama untuk menyelesaikan tugas tes secara manual?
Sebelum Anda menghabiskan waktu untuk pengujian otomatis, Anda perlu memeriksa apakah kami dapat mengevaluasi fungsi menggunakan kontrol game konvensional. Jika Anda ingin memastikan bahwa kunci Anda membuka kunci pintu, berikan kunci dan buka pintu untuknya. Membuat unit test untuk fungsi ini akan membuang-buang waktu - pengujian manual hanya membutuhkan beberapa detik.
2. Apakah sulit membuat test case secara manual?
Tes unit otomatis dibenarkan ketika ada yang diketahui dan sulit untuk mereproduksi kasus. Tes No. 7 dari "kelinci neraka" memeriksa bagaimana mereka berjalan di sepanjang tepian - sesuatu yang biasanya sulit dihindari oleh AI. Situasi seperti itu mungkin sulit atau tidak mungkin untuk direproduksi menggunakan kontrol game, dan tesnya mudah.
3. Apakah Anda tahu bahwa hasil yang diinginkan tidak akan berubah?
Desain gim sepenuhnya didasarkan pada iterasi, sehingga tujuan fitur dapat berubah seiring perubahan gim Anda. Bahkan perubahan kecil dapat membatalkan metrik yang digunakan untuk mengevaluasi fitur Anda, dan karenanya setiap unit menguji. Jika perilaku makhluk selama makan, tidur dan interaksi dengan pemain berubah beberapa kali, transisi dari titik A ke titik B tetap tidak berubah. Oleh karena itu, kode pergerakan dan tes unitnya tetap relevan sepanjang pengembangan.
4. Apakah regresi cenderung tidak diketahui?
Apakah Anda memiliki situasi ketika Anda menyelesaikan salah satu tugas terakhir sebelum mengirim permainan, dan tiba-tiba Anda menemukan kesalahan yang melanggar aturan? Dan dalam fungsi yang Anda selesaikan bertahun-tahun yang lalu. Game adalah sistem yang saling berhubungan raksasa, dan oleh karena itu wajar jika menambahkan fungsi baru B dapat menyebabkan kegagalan fungsi lama A.
Tidak begitu buruk ketika fungsi yang rusak digunakan di mana-mana (misalnya, lompatan) - Anda harus segera melihat kerusakan pada mekanika. Kesalahan yang ditemukan dalam pengembangan selanjutnya dapat mengganggu jadwal, dan setelah peluncuran dapat merusak gameplay.
5. Hal terburuk yang dapat terjadi saat menggunakan tes dan tanpa tes?
Membuat tes adalah salah satu bentuk manajemen risiko. Bayangkan Anda memutuskan apakah akan membeli asuransi kendaraan. Anda perlu menjawab tiga pertanyaan:
- Berapa premi asuransi bulanan?
- Seberapa besar kemungkinan mobil akan rusak?
- Seberapa mahal skenario terburuk jika Anda tidak diasuransikan?
Untuk TDD, kita dapat membayangkan kontribusi bulanan dalam bentuk biaya produksi untuk servis unit test kami, probabilitas kerusakan mobil sebagai kemungkinan mendapatkan bug, dan biaya penggantian mobil lengkap sebagai skenario terburuk untuk kesalahan regresi.
Jika diperlukan banyak waktu untuk membuat pengujian fitur, itu sederhana dan tidak mungkin diubah (atau dapat ditangani jika rusak dalam pengembangan kemudian), maka unit test dapat menyebabkan lebih banyak masalah daripada yang baik. Jika tes mudah dibuat, fungsinya tidak stabil dan saling berhubungan (atau kesalahannya akan memakan banyak waktu), maka tes akan membantu.
Batas Otomasi
Unit test bisa menjadi tambahan yang bagus untuk menemukan dan menghilangkan kesalahan, tetapi mereka tidak menggantikan kebutuhan untuk kontrol kualitas profesional dalam game skala besar. QA adalah seni yang membutuhkan kreativitas, penilaian subyektif dan komunikasi teknis yang sangat baik.