Para cambiar de ritmo, me gustaría hacer un pequeño registro de desarrollo. Hace algún tiempo, participé en un game jam e hice este juego, , un juego de rompecabezas corto en el que colocas queso alrededor del laberinto para atraer a los ratones. Fue divertido, pero evidentemente hubo algunas deficiencias. Of Mice and Bad Choices Uno de los principales es que el comportamiento de los ratones no es intuitivo. Los jugadores mencionaron que esperarían que los ratones se sintieran repelidos por un queso que no les gusta, no solo por congelarse. Además, implementar esta mecánica permitiría un diseño de rompecabezas mucho más rico. Entonces, creo que esta es una buena oportunidad para realizar pruebas automatizadas en Godot. Herramientas de prueba Hay algunos marcos de prueba disponibles para Godot 4, pero el que me llamó la atención es . GUT es bastante simple: Godot Unit Test (GUT) Se puede instalar desde AssetLib con un solo clic. Proporciona una clase que podemos ampliar para nuestros scripts de prueba: simplemente agregue funciones que comiencen con y escriba algunas afirmaciones (estructura típica de prueba unitaria). test_ Tiene una interfaz de usuario agradable con la capacidad de utilizar el depurador de Godot y ejecutar pruebas individuales. Se puede ejecutar desde CLI y en CI (pero me ocuparé de esto más adelante). Mi marco de prueba Para este caso particular, quería tener una forma de definir escenarios complejos, de la misma manera que defino los niveles para el juego: en el editor del motor en lugar de en el código (de esta manera, las pruebas estarían más cerca de la realidad). Por eso quiero hacer estas cosas: Tener una función de corredor único que toma un mapa y ejecuta las pruebas. Tener una colección de mapas, cada uno con un conjunto de escenarios (casos de prueba) para ejecutar. Tenga una forma de definir casos de prueba arrastrando y soltando: coloque un mouse y establezca dónde debería estar en N vueltas. Entonces, desenvolvamos esto. Definiciones de casos de prueba Definamos una nueva clase `MouseTestCase. Queremos que herede (ya que queremos colocarlo en una escena. Y queremos que encuentre uno de sus hijos (que nosotros mismos colocaremos en una escena): un mouse y su posición final esperada (como Marcador) Node2D 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) Ahora podemos ponerlo en escena y ¡estamos bien! Sabemos dónde comienza un mouse, sabemos dónde debe terminar y en cuántos pasos. Mapas de prueba Ahora, hagamos muchos más y hagamos un mapa para probar nuestro comportamiento repelente. Este comportamiento es algo complejo, por lo que queremos cubrir muchos casos ligeramente diferentes: Un ratón quiere alejarse del queso que no le gusta/ Un ratón quiere mantener la dirección del movimiento (es decir, evita giros) Un ratón prefiere los giros de izquierda a derecha y los giros en U. El mapa resultante que define 12 casos de prueba para cubrir este comportamiento se muestra arriba (imagínese lo tedioso que podría ser codificar todas esas coordenadas en código). Corredor de pruebas Lo único que queda por hacer es la función de ejecución de pruebas. La función necesita: Cargue el mapa que hemos definido anteriormente. Simule los pasos del juego hacia adelante hasta que se completen todos los casos de prueba. En cada paso, repita todos los casos de prueba y, si están terminados, verifique si se alcanza la posición esperada. El código es bastante simple. 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) Me imagino que esto evolucionará, pero la implementación actual es lo suficientemente buena por ahora. ¡Escribí las pruebas, implementé la mecánica y las pruebas realmente confirman que la mecánica está implementada correctamente! Discusiones Aquí, he mostrado una forma de abordar las pruebas en los juegos. Obviamente, hay muchas más cosas que mejorar aquí, y animo a los lectores a tomar el código y el marco y adaptarlos a sus necesidades. Como siempre, el código está disponible en GitHub: También puede echar un vistazo que presenta las pruebas. Para obtener puntos de bonificación, sería genial si alguien pudiera hacerlos funcionar en CI. Salud. https://github.com/d-lowl/of-mice-and-bad-choices al PR específico