Logo Hardware.com.br
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas

Aprendendo C com Desenvolvimento Orientado a Testes

#1 Por peczenyj 04/12/2007 - 14:50
Este é um exemplo didátivo: imagine que vc recebe a tarefa de implementar 5 funções em C a partir dos protótipos abaixo

Arquivo funcoes.h
[php]int ehpar(int); // o número indicado eh par ?
int ehprimo(int); // o número indicado eh primo ?
int maior(int,int); // qual dos dois numeros eh o maior ?
int menor(int,int); // qual dos dois numeros eh o menor ?
int soma(int,int); // retorna a soma de dois numeros
[/php]

Ok, esta é uma tarefa diferente, ninguem está pedindo para implementar um programinha que vai perguntar 'digite um numero', é para implementar apenas.

É claro que muita gente vai implementar pequenos programas e perder um tempão com menus e cores...

Pense diferente: unit test!

Arquivo test.h
[php]/*
* Modo de usar:
* test(condicao, mensagem)
*/
void test(int,char *);
/*
* Gera report dos testes
*/
void report(void);[/php]

Arquivo unit_test.h
[php]#include
#include "funcoes.h"
#include "test.h"

int main(void){
test(ehpar(2), "o numero 2 deve ser par");
test(!ehpar(3), "o numero 3 NAO deve ser par");
test(ehpar(4), "o numero 4 deve ser par");
test(!ehpar(5), "o numero 5 NAO deve ser par");

test(ehprimo(2), "o numero 2 deve ser primo");
test(ehprimo(3), "o numero 3 deve ser primo");
test(!ehprimo(4), "o numero 4 NAO deve ser primo");
test(ehprimo(5), "o numero 5 deve ser primo");

test(maior( 1,5)== 5, "entre 1 e 5, o 5 deve ser maior");
test(maior(10,5)==10, "entre 10 e 5, o 10 deve ser maior");
test(maior(-5,1)== 1, "entre 1 e -5, o 1 deve ser maior");
test(maior( 5,5)== 5, "entre 5 e 5, o 5 deve ser maior");

test(maior( 1,5)== 1, "entre 1 e 5, o 1 deve ser menor");
test(maior(10,5)== 5, "entre 10 e 5, o 5 deve ser menor");
test(maior(-5,1)==-5, "entre -5 e 1, o -5 deve ser menor");
test(maior( 5,5)== 5, "entre 5 e 5, o 5 deve ser menor");

test(soma( 5,5)== 10, "a soma de 5 com 5 deve ser 10");
test(soma(10,5)== 15, "a soma de 10 com 5 deve ser 15");
test(soma(-5,15)==10, "a soma de -5 com 15 deve ser 10");
test(soma( 0,5)== 5, "a soma de 0 com 5 deve ser 5");

report();
return 0;
}[/php]

Facil né? Eu descrevi os comportamentos básicos esperados das minhas 5 funções e perdi alguns minutos.

Agora é implementar, certo? Calma... vamos fazer primeiro algo que compile.

Arquivo funcoes.c
[php]#include "funcoes.h"

int ehpar(int a){
return -1; // so para retornar alguma coisa...
}
int ehprimo(int a){
return -1; // lembre-se: ansi C não tem tipo booleano, pesquise sobre isso... ;-)
// imprima o resultado de 1==1 e 1==2 pra vc ver smile.png
}
int maior(int a,int b){
return -1;
}
int menor(int a,int b){
return -1;
}
int soma(int a,int b){
return -1;
}[/php]

Compilando tudo

gcc -Wall funcoes.c test.c unit_test.c -o unit_test.exe


Vamos executar

[OK]: 'o numero 2 deve ser par'
Erro: 'o numero 3 NAO deve ser par'
[OK]: 'o numero 4 deve ser par'
Erro: 'o numero 5 NAO deve ser par'
[OK]: 'o numero 2 deve ser primo'
[OK]: 'o numero 3 deve ser primo'
Erro: 'o numero 4 NAO deve ser primo'
[OK]: 'o numero 5 deve ser primo'
Erro: 'entre 1 e 5, o 5 deve ser maior'
Erro: 'entre 10 e 5, o 10 deve ser maior'
Erro: 'entre 1 e -5, o 1 deve ser maior'
Erro: 'entre 5 e 5, o 5 deve ser maior'
Erro: 'entre 1 e 5, o 1 deve ser menor'
Erro: 'entre 10 e 5, o 5 deve ser menor'
Erro: 'entre -5 e 1, o -5 deve ser menor'
Erro: 'entre 5 e 5, o 5 deve ser menor'
Erro: 'a soma de 5 com 5 deve ser 10'
Erro: 'a soma de 10 com 5 deve ser 15'
Erro: 'a soma de -5 com 15 deve ser 10'
Erro: 'a soma de 0 com 5 deve ser 5'
--------------
Total = 20, Pass = 5, Fail = 15


Algumas funções acertaram o resultado por acaso. Agora vem uma técnica bem interessante: codifique cada função, compile e rode de novo os testes.

Faça isso até que todos os testes estejam passando. Depois implemente novos testes (pelo menos mais dois de cada), compile e rode de novo.

Continua funcionando? Aparentemente vc fez um ótimo trabalho!

Perceba que eu disse ANTES tudo o que as funções deveriam fazer, depois eu implementei smile.png

O ultimo codigo para todo o exemplo funcionar:

Arquivo test.c
[php]#include
#include "test.h"
int total=0;
int pass =0;
int fail =0;
void test(int condicao,char *msg){
total++;
if(!condicao){
fail++;
printf("Erro: '%s'\n",msg);
}else{
pass++;
printf("[OK]: '%s'\n",msg);
}
}
void report(void){
printf("--------------\n");
printf("Total = %d, Pass = %d, Fail = %d\n",total,pass,fail);
}[/php]

Agora mãos na massa. E deixem as corezinhas pra quanto todos os testes estiverem funcionando smile.png

PS: Aprendam a criar um makefile (com uma target chamada test) e tudo ficara muito mais facil ainda!
jofrelscalvet
jofrelscalve... Veterano Registrado
1.3K Mensagens 51 Curtidas
#4 Por jofrelscalve...
05/12/2007 - 16:47
Acho que vou aproveitar o tópico pra fazer uma pergunta que me atormenta há tempos:
Como testar uma interface gráfica? (Se o dado digitado for inválido aparece a msg x, se for válido aparece o botão y)
Sei que existem programas pra isso, mas me parece algo muito complicado. Seria possivel algum exemplo? Tenho especial interesse em aplicações à web
Melhore o futuro do fórum: Diga se a dica funcionou ou conte-nos como conseguiu resolver a sua dúvida!
Se eu errar ou for pouco claro, reclame! Quando possivel eu tentarei melhorar.
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#6 Por peczenyj
05/12/2007 - 20:20
jofrelscalvet disse:
Como testar uma interface gráfica? (Se o dado digitado for inválido aparece a msg x, se for válido aparece o botão y)


Depende da interface e dos mecanismos de reconhecimento.

Por exemplo, se vc tem uma estrutura onde a camada 'grafica' é separada do resto do programa vc pode criar uma camada 'grafica' de mentira e efetuar testes, porém isso só garante a qualidade das outras camadas (como a camada de controle e modelo/persistencia, no caso de sistemas com MVC).

Se vc quer testar a camada gráfica mesmo, ai vc tem diversas receitas:

- Se é grafico feita com caracteres de escape ASCII (como telas de dialog), vc pode tratar como arquivos texto e fazer as interações via uma ferramenta chamada expect.

- Se é web existe diversos programas que podem ser usados como: WebTest (Canoo), Selenium, Rational XDE Tester($$$), Quick Test Pro ($$$), etc.

- Se é uma interface GTK, X-window, MS-Windows, etc... devem ferramentas específicas (pro mundo windows tem o Quick Test Pro, Rational Functional Tester, etc).

Hoje eu fiz a seguinte experiência: eu peguei o COM do internet explorer e criei um vbscript que carregava uma pagina, escrevia em alguns campos, clicava um botão e analisava o resultado em uma tabela. Semelhante a isso tem este exemplo: http://scriptorium.serve-it.nl/view.php?sid=30

Testes web são possiveis de diversas formas: vc pode criar um framework javascript e carregar a pagina em um frame ou iframe e, então, analisar os objetos DOM da pagina. Requer paciencia, mas é divertido.

------------

Quero incrementar esse 'framework' de testes unitarios pra C e deixar alguns exercicios pra galera que vai começar o próximo semestre. Talvez eu consiga convencer algum professor, sei la.

Outra coisa: está na moda falar em BDD (Behavior Driven Development), que é uma evolução conceitual do TDD. Ao inves de pensar em testes, vc pensa no comportamento, a sintaxe muda mas o efeito é o mesmo (pra melhor).
philix
philix Super Participante Registrado
946 Mensagens 14 Curtidas
#7 Por philix
06/12/2007 - 08:25
Testes web são possiveis de diversas formas: vc pode criar um framework javascript e carregar a pagina em um frame ou iframe e, então, analisar os objetos DOM da pagina. Requer paciencia, mas é divertido.


A extensão Firebug que vc instala no Firefox faz isso para vc, é muito bom o firebug, vc "debuga" até o CSS...
"A Matemática é a ginástica mental necessária na tentativa da compreenssão do universo" Linus Torvalds
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#8 Por peczenyj
06/12/2007 - 10:43
Ok, mas uma coisa é vc explorar o html via alguma ferramenta, outra coisa é vc automatizar um teste.

Por exemplo, vc tem um caso de teste assim:

- entra na pagina, preenche os campos e clica em ok.
- sai da pagina e entra de novo.
- vc deve ver os mesmos dados que vc digitou antes.

Se eu tenho determinado os campos e quais valores eu vou entrar, automatizar isso é questão de ter uma ferramenta que reconheça os objetos e execute as interações.

Outro caso de teste seria assim:

- Preencha o campo "email" com um email invalido (ex: http://google.com )
- Clique em ok
- Deve ser emitida uma mensagem de erro do tipo "X"

Aqui é mais 'complexo', pois a mensagem pode ser no html, em cima, pode ser um alert do javascript, pode ser a mesma pagina recarregada via ajax com uma mensagem, etc. E a borda do campo pode ficar vermelha, azul, roxa...

O Rails tem um esquema de testes internos sensacional! Vale a pena ver smile.png

Mas o firebug é show de bola, porém tem seus problemas: ele pode interferir na pagina. Eu ja fiz o teste, fui fuçar no gmail e ficou tudo louco, mas deve ser um caso em 1024 smile.png
jofrelscalvet
jofrelscalve... Veterano Registrado
1.3K Mensagens 51 Curtidas
#9 Por jofrelscalve...
13/12/2007 - 01:15
Agradeço muito a ajuda.
Depois de ler a resposta do peczenyj fiquei até com vontade de inventar um teste, mas fiquei enrolado com o trabalho (e $ tem prioridade...), na "volta" brinquei um pouco com o selenium-IDE, que é muito legal, mas me fez ficar com vontade de comprar um micro novo, pois o firefox ocupava mais de 95% de processamento por cerca de 1 minuto no "hello world".
Revendo o tópico notei que falta algo importante: não foi mencionado o porquê. Assim vou dar um exemplo web que explica as motivações que levam as "metodologias ageis" a fazerem sucesso.
Exemplo de porque usar o desenvolvimento orientado a testes
Você faz um site, depois de alguns meses no ar aparece alguem reclamando que no navegador que ele usa o site não funciona. Você quebra a cabeça e faz umas pesquisas e descobre qual a peculiaridade do navegador causa o problema e como burlá-la, e ao corrigi-la você inadvertidamente aperta alguma tecla. Você testa no navegador "novo" e no IE e funciona. 2 dias depois você tem uma enxurrada de reclamações que o site deixou de funcionar em todos os navegadores compativeis com o padrão da mozilla (netscape, firefox,...) .
Ou seja a cada modificação o ideal é testar tudo (de novo se já foi testado na modificação anterior...) , grandes empresas dividem os testes em 2 grupos, os que devem ser testados "agora", e os que são executados apenas 1 vez por semana (pelo menos foi o que eu li em algum lugar).
Melhore o futuro do fórum: Diga se a dica funcionou ou conte-nos como conseguiu resolver a sua dúvida!
Se eu errar ou for pouco claro, reclame! Quando possivel eu tentarei melhorar.
peczenyj
peczenyj Geek Registrado
3K Mensagens 75 Curtidas
#10 Por peczenyj
13/12/2007 - 09:54
jofrelscalvet,

Veja se não é possivel utilizar o WebTest da Canoo ou substituir alguns testes por requests do tipo POST/GET via shell script (utilizando o curl).

http://curl.haxx.se/docs/httpscripting.html

Acredito que ambas as formas são de boa performance, porém com algumas limitações.

http://mguillem.wordpress.com/2007/10/29/webtest-vs-selenium-webtest-wins-13-5/

Se vc utilizar a ferramenta certa pro trabalho certo, pode fazer bastante coisa legal.

Recomendo a leitura
http://gc.blog.br/2007/09/26/voce-automatiza-seus-testes-de-aceitacao/

Ok, saimos do mundo C para o mundo Web, porém ambos tem o mesmo cerne: programadores profissionais escrevem testes.
© 1999-2024 Hardware.com.br. Todos os direitos reservados.
Imagem do Modal