Biraz değişiklik olsun diye, biraz geliştirici günlüğü tutmak istiyorum. Bir süre önce bir oyun yarışmasına katıldım ve bu oyunu - Fareler ve Kötü Seçimler - fareleri dışarı çekmek için labirentin etrafına peynir yerleştirdiğiniz kısa bir bulmaca oyunu yaptım. Eğlenceliydi ama bazı eksiklikler olduğu belliydi.
Bunlardan en önemlilerinden biri farelerin davranışlarının sezgisel olmamasıdır. Oyuncular, farelerin sadece dondurulmasını değil, sevilmeyen bir peynirin de itilmesini beklediklerini belirttiler. Ayrıca, bu mekaniğin uygulanması çok daha zengin bir bulmaca tasarımına olanak tanıyacaktır.
Dolayısıyla bunun Godot'ta otomatik testlerin yapılabilmesi için iyi bir fırsat olduğunu düşünüyorum.
Test Araçları
Godot 4 için kullanılabilen birkaç test çerçevesi var, ancak I'imi yakalayan Godot Unit Test (GUT) oldu. GUT oldukça basittir:
- Tek tıklamayla AssetLib'den kurulabilir.
- Test komut dosyalarımız için genişletebileceğimiz bir sınıf sağlar: sadece
test_
ile başlayan işlevler ekleyin ve bazı iddialar yazın; tipik birim test yapısı.
- Godot'nun hata ayıklayıcısını kullanma ve bireysel testler yürütme yeteneğine sahip hoş bir kullanıcı arayüzüne sahiptir.
- CLI'den ve CI'dan çalıştırılabilir (ancak bununla daha sonra ilgileneceğim).
Test Çerçevem
Bu özel durum için, karmaşık senaryoları, oyunun seviyelerini tanımladığım gibi, kod yerine motor editöründe tanımlamanın bir yoluna sahip olmak istedim (bu şekilde testler gerçeğe daha yakın olurdu). Bu nedenle şunları yapmak istiyorum:
- Haritayı alan ve testleri çalıştıran tek bir koşucu işlevine sahip olun.
- Her biri yürütülecek bir dizi senaryoya (test senaryolarına) sahip bir harita koleksiyonuna sahip olun.
- Test senaryolarını sürükle-bırak yöntemiyle tanımlamanın bir yolunu bulun: bir fare yerleştirin ve N dönüşte olması gereken yeri ayarlayın.
O halde bunu açalım.
Test Senaryosu Tanımları
Yeni bir `MouseTestCase` sınıfı tanımlayalım. Onun Node2D
miras almasını istiyoruz (onu bir sahneye yerleştirmek istediğimiz gibi. Ve onun alt öğelerinden birini (sahneye kendimiz yerleştireceğimiz) bulmasını istiyoruz: bir fare ve beklenen son konumu (İşaretçi olarak)
extends Node2D class_name MouseTestCase @export var steps_left = 0 # How many steps to simulate @export var done = false @onready var mouse: Mouse = $Mouse @onready var expected_position = SnapUtils.get_tile_map_position($TestMarker.position)
Artık bunu sahneye koyabiliriz ve iyiyiz! Farenin nerede başladığını, nerede bitmesi gerektiğini ve kaç adımda biteceğini biliyoruz.
Haritaları Test Et
Şimdi bunlardan bir grup daha oluşturalım ve itici davranışımızı test etmek için bir harita hazırlayalım.
Bu davranış biraz karmaşık olduğundan, birbirinden biraz farklı birçok durumu ele almak istiyoruz:
- Fare beğenmediği peynirden uzaklaşmak istiyor/
- Fare hareket yönünü korumak istiyor (yani dönüşlerden kaçınıyor)
- Fare sola sağa dönüşleri ve U dönüşlerini tercih eder
Bu davranışı kapsayacak 12 test senaryosunu tanımlayan sonuçta ortaya çıkan harita yukarıda gösterilmiştir (tüm bu koordinatları koda sabit kodlamanın ne kadar sıkıcı olabileceğini hayal edin).
Test Çalıştırıcısı
Yapılacak tek şey test çalıştırıcı işlevidir. Fonksiyonun şunları yapması gerekir:
- Yukarıda tanımladığımız haritayı yükleyin.
- Tüm test senaryoları tamamlanana kadar oyunun ileri adımlarını simüle edin.
- Her adımda, tüm test senaryolarını yineleyin ve bunlar yapıldıysa beklenen konuma ulaşılıp ulaşılmadığını kontrol edin.
Kod oldukça basit.
func run_level_with_mouse_test_cases(map_path: String): var level = load(map_path) map.load_level(level) var cases = MouseTestCase.cast_all_cases(get_tree().get_nodes_in_group(MouseTestCase.MTC_GROUP_NAME)) while (cases.any(func(case): return not case.done)): map.move_mice() for case in cases: if not case.done: case.steps_left -= 1 if case.steps_left == 0: case.done = true assert_eq(case.get_mouse_position(), case.expected_position, case.get_parent().name+"/"+case.name)
Bunun gelişeceğini hayal ediyorum, ancak mevcut uygulama şimdilik yeterince iyi. Testleri yazdım, mekaniği uyguladım ve testler aslında mekaniğin doğru şekilde uygulandığını doğruladı!
Tartışmalar
Burada oyunlardaki testlere yaklaşmanın bir yolunu gösterdim. Açıkçası burada geliştirilecek daha pek çok şey var ve okuyucuları kodu ve çerçeveyi alıp ihtiyaçlarına göre uyarlamaya teşvik ediyorum.
Her zaman olduğu gibi kod GitHub'da mevcuttur: https://github.com/d-lowl/of-mice-and-bad-choices Ayrıca testi tanıtan özel PR'ye de göz atabilirsiniz. Bonus puan olarak eğer birisi bunları CI'da çalıştırabilirse bu harika olur. Şerefe.