Programando Juegos Sociales en Línea (Parte 6) Armando y Probando el Juego y los Servicios con TDD y QUnit

Published on Author lopezLeave a comment

Anterior Post

En mi anterior post, comenté la nueva versión 1.1 (hay ahora una 1.2 Beta) del Windows Azure Toolkit for Social Games. Tiene juegos simples para demostrar el uso de Javascript, HTML5, procesamiento de movidas del juego, uso de Azure web roles y worker roles. Veamos de explorar en este post el armado de la lógica del juego, en Javascript, usando TDD (Test-Driven Development) y QUnit.

Hay tests en línea en:

http://watgames4.cloudapp.net/Test

Ejecutemos los test de Tic Tac Toe Game Logic:

http://watgames4.cloudapp.net/Samples/ClientTest/TicTacToeGameTest

Esta página está usando QUnit para tests en el cliente usando Javascripot. Escribí posts introductorios:

TDD with Javascript and QUnit
TDD con Javascript y QUnit

La página que visitamos está probando la lógica del juego de Ta Te Ti. Recordemos, cada juego está implementado en partes, la lógica es una de ellas:

El código cliente reside en TicTacToeGame.js dentro del proyecto SocialGames.Web. Sus primeras líneas:

TTTColor = { Empty: 0, Cross: 1, Circle: 2 };
function TicTacToeGame() {
    this.board = [
     [TTTColor.Empty, TTTColor.Empty, TTTColor.Empty],
     [TTTColor.Empty, TTTColor.Empty, TTTColor.Empty],
     [TTTColor.Empty, TTTColor.Empty, TTTColor.Empty]
     ];
}
TicTacToeGame.prototype.move = function (x, y, color) {
    this.board[x][y] = color;
};
TicTacToeGame.prototype.isEmpty = function (x, y) {
    return this.board[x][y] == TTTColor.Empty;
};
....

La vista razor (TicTacToeGameTest.cshtml) fue escrita al mismo tiempo que la lógica, usando TDD (Test-Driven Development). Veamos los primeros tests:

test("Create Empty Board", function () {
    var game = new TicTacToeGame();
    for (var x = 0; x < 3; x++)
        for (var y = 0; y < 3; y++)
            ok(game.isEmpty(x, y));
    equal(game.isTie(), false);
    equal(game.hasWinner(), false);
});
test("Valid Moves on Empty Board", function () {
    var game = new TicTacToeGame();
    for (var x = 0; x < 3; x++)
        for (var y = 0; y < 3; y++) {
            ok(game.isValid(x, y, TTTColor.Cross));
            ok(game.isValid(x, y, TTTColor.Circle));
        }
});
test("No Winner in Empty Board", function () {
    var game = new TicTacToeGame();
    equal(game.getWinner(), TTTColor.Empty);
});
test("Get Winner in First Row", function () {
    var game = new TicTacToeGame();
    game.move(0, 0, TTTColor.Cross);
    game.move(1, 0, TTTColor.Cross);
    game.move(2, 0, TTTColor.Cross);
    equal(game.getWinner(), TTTColor.Cross);
    equal(game.isTie(), false);
    equal(game.hasWinner(), true);
});

La idea es avanzar de a pequeños pasos, test por test, diseñando la API de la lógica del juego, y su conducta esperada. De esta manera, vamos avanzando sin gastar tanto tiempo en prueba manual, y menos tiempo en depuración. Esto es recomendable, pero más aún cuando se trabaja con un lenguaje dinámico como Javascript. Una batería de pruebas puede salvarnos el día en caso de un refactoreo grande. Vean que el Four In A Row siguió un camino similar.

Bien, no todo puede ser testeado fácilmente, o construido usando TDD. Algunos de los servicios agnósticos del juego (es decir, independientes del juego que se implemente) estan usando Ajax y Blob Storage, y para probarlos debemos considerar el uso de Ajax asincrónico (pueden comenzar construyendo tests sincrónicos si quieren). Pueden ver:

http://watgames4.cloudapp.net/Test/ServerInterfaceTest

(Para esta página, deben ingresar usando una cuenta de Facebook o de Windows Live ID, el ejemplo usa Federated Security y Access Control Service (ACS))

Esta vez, el sistema bajo prueba es el Service Interface:

Hay algunos trucos en el código de prueba (ServerInterfaceTest.cshmlt), un fragmento:

test("Call User/Verify", function () {
    var success = function (result) { ok(true); start(); };
    var error = ajaxGetError;
    stop(10000);
    expect(1);
    si.sendAjaxGet(apiURL + "user/verify", success);
});

expect es una función provista por QUnit que prepara al framework para recibir un ok(true) alguna vez durante la ejecución de la prueba. Esa confirmación se incluye en la función callback success que será llamada luego de la ejecución exitosa de la llamada asincrónica .sendAjaxGet. La vida Async no es fácil 😉

Más análisis del código en próximos posts. Debería adaptar algún juego para que use Node.js para procesar sus jugadas.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *