segunda-feira, 4 de julho de 2011

OpenCTF - Teste de componentes


De acordo com a descrição no site do projeto, o OpenCTF é um framework voltado para teste de componentes (visuais ou não) com base no DUnit.
Basicamente você irá criar regras e com isso garantir que todos os membros da equipe ou do projeto estão sendo seguido-as.
Vamos imaginar algumas regras:
1) Todos os seus Forms devem herdar de um determinado FormX;
2) Verificar se o TabOrder está correto;
3) Todos os itens de menu devem ter um método associado ao evento OnClick;
4) Todos os componentes devem ser nomeados, ou seja, não pode ter o nome padrão como Button1, Label1, Edit1 e etc;
5) Validas os prefixos dos nomes dos componentes;
Bem, já deu para perceber que a lista pode ser imensa.
Uma outra vantagem deste framework é que você só precisa escrever o teste, ou melhor, a regra uma única vez. Creio que não necessidade exemplificar aqui o uso do mesmo, pois os exemplos nele contidos são suficientemente claros.

segunda-feira, 27 de junho de 2011

DUnit - Testando elementos da GUI

Eu não sabia que era possível usar o DUnit para fazer testes de GUI até então. Durante um curso de Testes aqui na empresa, enquanto o instrutor apresentava algumas ferramentas para JAVA, comecei a fuçar a internet e descobri é possível sim testar os elementos da minha GUI.
Abaixo irei mostrar uma calculadora simples, destas que a gente faz quando está iniciando.
No exemplo usarei o Delphi XE, mas creio que funcionará em outras versões.
Não vou mostrar aqui o código da calculadora nem comentar sobre o mesmo por considerar desnecessário e poque no final do post vou disponibilizar o projeto para download.
Ela basicamente tem três Edits (edtNum1, edtNum2 e edtResult) e dois botões (btnSomar e btnMultiplicar), o resto é com vocês.
Também não vou ensinar a criar um projeto de testes usando o DUnit porque não é o intuito deste post.
A primeira coisa a se fazer é adicionar ao uses da unit de testes, neste caso a unit do formulário da calculadora como mostrado a seguir.
uses TestFramework, TestExtensions, GUITesting, Unit1;
O DUnit sempre que um teste é iniciado ele executar o método SetUp, e sempre que um teste é finalizado ele executa o TearDown. Para este tipo de teste isto não é desejado pois o estado da aplicação sempre será alterado cada vez que um teste for iniciado, então para resolver o problema vamos precisar de duas coisas:
Primeiro vamos criar uma subclasse de TTestSetup da unit TestExtensions. TTestSetup é um Decorator para TTestCase. Com isto você o SetUp e o TearDown será executado apenas um vez.
type
TFormSetup= class(TTestSetUp)
private
FFormCalc: TForm1;
protected
procedure SetUp; override;
procedure TearDown; override;
end;
Abaixo temos a implementação do SetUp e do TearDown.
procedure TFormSetup.SetUp;
begin
FFormCalc := TForm1.Create(Application);
FFormCalc.Show;
inherited;
end;

procedure TFormSetup.TearDown;
begin
FFormCalc.Free;
inherited;
end;
Agora estamos pronto para criar o nosso teste, então vamos lá.
A primeira coisa a se fazer é criar a nossa classe de teste, note que ela deve herdar de TGUITestCase e não de TTestCase comumente utilizada.
TFormCalcTests = class(TGUITestCase)
private
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
published
procedure TesteDigitaTexto;
procedure TesteSoma;
procedure TesteMultiplicacao;
end;
Precisamos adicionar ao Uses a unit Forms e StdCtrls.
uses Forms, StdCtrls, TestFramework, TestExtensions, GUITesting, Unit1;
Agora vamos implementar os três testes.
procedure TFormCalcTests.TesteDigitaTexto;
begin
Edit1 := FindControl('edtNum1') as TEdit;
Edit1.Text := '2';
CheckEquals('2', Edit1.Text);
Edit2 := FindControl('edtNum2') as TEdit;
EnterTextInto(Edit2, '3');
CheckEquals('3', Edit2.Text);
end;

procedure TFormCalcTests.TesteMultiplicacao;
begin
Click('btnSomar');
Edit3 := FindControl('edtResult') as TEdit;
CheckEquals('5', Edit3.Text);
end;

procedure TFormCalcTests.TesteSoma;
begin
Click('btnMultiplicar');
Edit3 := FindControl('edtResult') as TEdit;
CheckEquals('6', Edit3.Text);
end;
Propositalmente eu criei os testes dependentes, para mostrar que o formulário fora instanciado apenas uma vez.
Note que na linha 7 eu não atribui o valor direto na propriedade Text do Edit2, ao invés disto usei o método EnterTextInto, também para mostrar uma forma de simular o pressionamento das teclas. Porém neste teste você não vai perceber por ser muito rápido, para ver o efeito altere o teste para atribuir mais de um caractere a cada edit. Se ainda assim ficar muito rápido para perceber, faça um override do Create e altere a propriedade ActionDelay que por padrão é de 100ms;
constructor TFormCalcTests.Create(MethodName: string);
begin
inherited Create(MethodName);
ActionDelay := 300;
end;
Por último precisamos registrar o teste, que neste caso será de maneira diferente.
initialization
RegisterTest(TFormSetup.Create(TFormCalcTests.Suite));

end.
Fontes:https://bitbucket.org/MarcioMartins/dunittestgui