quarta-feira, 11 de fevereiro de 2009

Criando testes no PHPUnit/Selenium que rodem com o symfony/doctrine/phing/phpunit

Ingredientes

symfony+doctrine: framework de desenvolvimento e ORM
phpunit: para testes unitários
phing: para fazer o build, rodar os testes, gerar a documentação, lavar a roupa, etc...

Problemas a se Vencer:

O phpunit, quando roda pela linha de comando, não carrega as configurações do projeto do symfony.

Alguns testes do selenium precisam de acesso à api do symfony para configurar o ambiente e ter acesso aonde o browser não tem.

Descrição da Solução:

Para isso precisamos carregar as configurações do symfony/docrine. Claro que é bom fazer isto uma vez só para não pesar nos testes. Porém precisamos fazer isto de uma maneira que não prenda muito os testes a um diretório específico e que não seja repetitiva.

O phpunit, quando rodado pelo phing, não considera as suites de teste, rodando todos os testes separadamente. Por isso, o setUp() da suite, que poderia parecer um bom local, na verdade não é pois ele será desconsiderado pelo phing. Escolhemos então o setUp de cada classe teste. Para não repetir o código, criamos uma classe da qual extendemos todos os nossos testes. Assim nossas classes já herdam o setUp. Como o autoload do symfony ainda não foi carregado, precisamos informar para o phpunit o caminho da nossa classe caso ela não esteja no include.

Solução Proposta:


### classe pai

class Sf_PHPUnit_Extensions_SeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
function setUp()
{
if ( SF_APP_NAME != '' )
{
define( 'SF_APP_NAME', 'frontend' );
define( 'SF_ENV', 'test' );
define( 'SF_CONN', 'doctrine' );
// ajuste o caminho abaixo de acordo com o local onde vc por esta classe
require_once(dirname(__FILE__).'/../../../../config/ProjectConfiguration.class.php');
// busca as configurações do projeto
$configuration = ProjectConfiguration::getApplicationConfiguration( SF_APP_NAME , SF_ENV, true);
sfContext::createInstance($configuration);
sfContext::getInstance()->getUser()->initSession('phpunit');
// em alguns contextos as linhas abaixo podem ser úteis, mas não lembro quais agora :)
//$databaseManager = new sfDatabaseManager($configuration);
//$databaseManager->loadConfiguration();
}

$this->setBrowser("firefox");
// "solução de contorno" para definir se o teste está no ambiente de desenv ou homolog.
if(isset($_SERVER[HOMEDRIVE]) && $_SERVER[HOMEDRIVE] == 'C:') {
$this->setBrowserUrl("http://aliaslocal/");
}
else {
// ip ou alias do servidor...
$this->setBrowserUrl("http://10.1.1.234/");
}
}
}

### classe filha


require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
// lembrar que este require é necessário pois o autoload do symfony ainda não foi carregado neste ponto.
require_once dirname(__FILE__).'/../../../plugins/sfUtil/lib/test/SF_PHPUnit_Extensions_SeleniumTestCase.php';

class LoginSeleniumTest extends SF_PHPUnit_Extensions_SeleniumTestCase
{

function setUp() {
// lembrar de chamar o setUp do pai caso precise extender aqui...
parent::setUp();
$this->doSomeMoreSetup();
}
// ...

Conclusão:

Claro que devem existir inúmeras soluções para este problema. Caso você tenha algo a acrescentar ou alguma crítica construtiva, certamente isto vai melhorar ainda mais a nossa proposta.

Nenhum comentário:

Postar um comentário