Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

17 Feb 10 Agile Brazil 2010 – A chamada para trabalhos está aberta!

Estou de férias, e eu não ia escrever nada aqui no blog antes de voltar ao trabalho, mas isto merece o post :D
A chamada de trabalhos para o Agile Brazil 2010 esta aberta.
Se você tem algo interessante sobre Agile para falar, envie sua proposta de palestra, tutorial ou workshop por este link.

A Agile Brazil 2010 é um evento nacional organizado por representantes das principais comunidades ágeis brasileiras. Junte-se a nós submetendo trabalhos, participando do concurso do logo e divulgando o evento.

Acompanhe as novidades do @agilebrazil pelo Twitter.

O evento vai acontecer em Porto Alegre de 22 a 25 de Junho 2010.

Espero ver alguns de vocês por lá!

Tags: , , , , , , , ,

15 Jul 08 Testes unitários em C++ para um programador Java!

English version here
Eu trabalhei com C++ quando iniciei no mundo da programação (entre 1997 e 2000), mas na época eu trabalhava com o Borland C++ Builder e o Microsoft Visual C++, naquela época eu ainda não tinha ouvido falar em testes unitários, depois disto eu trabalhei com Delphi, PHO, ASP, ColdFusion, …
Desde 2002 eu trabalhei a maior parte do tempo com Java, e aprendi muito neste período, muitas boas práticas, muito sobre orientação a objetos e principalmente, aprendi a amar os testes unitários.
Pouco tempo atrás eu voltei a trabalhar com C++, mas já viciado em testes unitários, e querendo aplica-los ao meu código C++ também, e este post é um exemplo bem curto de como um programador Java pode trabalhar com C++ utilizando testes unitários.

Um projeto C++ começa por um Makefile, eu estou acostumado com o ANT e não gosto da idéia de listar todos os meus arquivos fonte na configuração de build como a maior parte dos exemplos de Makefiles fazem, então eu criei um Makefile simples, mas bastante flexível para o meu projeto.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TESTDIRECTORIES := test
DIRECTORIES := src
SOURCES := $(foreach dir,$(DIRECTORIES),$(wildcard $(dir)/*.cpp))
TESTSOURCES := $(foreach dir,$(TESTDIRECTORIES),$(wildcard $(dir)/*.cpp))
OBJECTS := $(patsubst %.cpp,%.obj,$(SOURCES))
TESTOBJECTS := $(patsubst %.cpp,%.obj,$(TESTSOURCES))
TESTOBJECTS += $(filter-out src/main.obj,$(OBJECTS))
TARGET := example
LINK := g++
CC := g++
CFLAGS := -c
LFLAGS :=
 
all: $(OBJECTS)
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS)
 
test: $(TESTOBJECTS)
	$(LINK) $(LFLAGS) -lcppunit -o $(TARGET)_unit $(TESTOBJECTS) 
	./$(TARGET)_unit
 
%.obj:%.cpp
	$(CC) $(CFLAGS) -o $*.obj $*.cpp

Com este Makefile, todos os arquivos .cpp que estiverem no diretório src farão parte do executável gerado, mais diretórios podem ser adicionados simplesmente atualizando a variável DIRECTORIES, a mesma coisa acontece com o diretório test e a variável TESTDIRECTORIES para os testes unitários.
O truque aqui é a combinação das funções foreach e wildcard, a função pathsubst é usada para alterar as extensões de .cpp para .obj e a função filter-out é usada para remover o main.cpp dos testes unitários pois este arquivo é apenas o ponto de entrada para o executável principal.
Este Makefile é o mais próximo que eu consegui chegar da funcionalidade do ANT para programação C++, claro que ela pode ser melhorada, considerando que eu não sou um especialista em Makefiles.
Mas o Makefile não é o motivo deste post, estou escrevendo para contar para vocês sobre o CppUnit, uma ótima implementação xUnit para C++.
Eu comecei o projeto escrevendo o “executador de testes” do CppUnit:
testRunner.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>
 
int main (int argc, char* argv[])
{
    // informs test-listener about testresults
    CPPUNIT_NS :: TestResult testresult;
 
    // register listener for collecting the test-results
    CPPUNIT_NS :: TestResultCollector collectedresults;
    testresult.addListener (&collectedresults);
 
    // register listener for per-test progress output
    CPPUNIT_NS :: BriefTestProgressListener progress;
    testresult.addListener (&progress);
 
    // insert test-suite at test-runner by registry
    CPPUNIT_NS :: TestRunner testrunner;
    testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ());
    testrunner.run (testresult);
 
    // output results in compiler-format
    CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr);
    compileroutputter.write ();
 
    // return 0 if tests were successful
    return collectedresults.wasSuccessful () ? 0 : 1;
}

CppUnit é mito flexível, permitindo diversos tipos de saída para os resultados dos testes, mas escreverei sobre isto em outro post, a idéia atrás deste “executador” é a utilização do registro de testes do CppUnit, o que torna a vida muito mais fácil.
O registro de testes é bem próximo ao fileset passado a task junit do ant, mas os testes se registram sozinhos.
Depois do “executador de testes” pronto, podemos começar a escrever os testes unitários.
Em C++ diferente do Java, são necessários dois arquivos para cada classe, um cabeçalho e uma implementação.
Então, vamos começar com o cabeçalho.
mainTest.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef MAINTEST_H
#define MAINTEST_H
 
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include "../src/HelloWorld.hpp"
 
using namespace std;
 
class MainTest : public CPPUNIT_NS :: TestFixture
{
    CPPUNIT_TEST_SUITE (MainTest);
    CPPUNIT_TEST (testHello);
    CPPUNIT_TEST_SUITE_END ();
 
    public:
        void setUp (void);
        void tearDown (void);
        void testHello (void);
    private:
        HelloWorld *hello;
};
CPPUNIT_TEST_SUITE_REGISTRATION (MainTest);
#endif

Neste cabeçalho temos uma declaração de classe simples, extendendo TestFixture do namespace do CppUnit.
C++ não possui reflexão, por isto o CppUnit possui algumas macros para definir o teste, que podem ser vistas no início da declaração da classe, será necessária uma linha com CPPUNIT_TEST para cada método de teste que você declarar.
A linha: CPPUNIT_TEST_SUITE_REGISTRATION (MainTest);
Faz a mágica do auto registro dos testes.
Com isto pronto, você pode começar a implementar a classe de testes como faria em java:
mainTest.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "mainTest.hpp"
 
void MainTest::setUp(){ 
	hello = new HelloWorld("Test");
}
 
void MainTest::tearDown(){
	delete hello;
}
 
void MainTest::testHello(){
	string expected("Hello Test\n");
	CPPUNIT_ASSERT_EQUAL(expected,hello->sayHello());
}

Como no JUnit existem os métodos setUp e tearDown que são executados antes e depois de cada um dos testes, e o método testHello possui o código do teste (ja que só foi implementado um para este exemplo).
As asserções no CppUnit são feitas utilizando macros.
O CppUnit disponibiliza as seguintes asserções:

  • CPPUNIT_ASSERT(condition)
  • CPPUNIT_ASSERT_MESSAGE(message,condition)
  • CPPUNIT_FAIL( message )
  • CPPUNIT_ASSERT_EQUAL(expected,actual)
  • CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual)
  • CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta)
  • CPPUNIT_ASSERT_THROW( expression, ExceptionType )

Muito menos do que no JUnit, mas o suficiente para a grande maioria dos casos.
Depois do teste pronto, agora precisamos escrever o código para que os testes passem.
HelloWord.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <iostream>
 
#ifndef MAIN_HPP
#define MAINHPP
class HelloWorld{
private:
	std::string name;
public:
	HelloWorld(char* name);
	std::string sayHello();
};
#endif

E a implementação:
HelloWord.cpp

1
2
3
4
5
6
7
8
9
10
11
#include "HelloWorld.hpp"
 
HelloWorld::HelloWorld(char* name){
	this->name = name;
}
 
std::string HelloWorld::sayHello(){
	std::string result("Hello ");
	result = result + name + "\n";
	return result;
}

Para executar os testes, basta você executar no console:
make test
Agora que todos os testes foram escritos e estão passando, o último passo é escrever o código para inicializar a aplicação:
main.cpp

1
2
3
4
5
6
7
8
#include "HelloWorld.hpp"
int main(int argc, char** argv){
	if (argc >= 2) {
		HelloWorld* hello = new HelloWorld(argv[1]);
		std::cout << hello->sayHello();
		delete hello;
	}
}

E você tem a sua primeira aplicação test driven escrita em C++!
PS.: se você esta utilizando o Makefile que escrevi, lembre que o código da aplicação deve ficar no diretório src e o código de testes no diretório test.
PS2.: O exemplo foi testado em um linux com o CppUnit instalado pelo gerenciador de pacotes, se você quiser instalar o cppunit usando o código fonte ou for executar em outra plataforma lembre-se de atualizar o CFLAGS com os caminhos de influde corretos e o LFLAGS com o caminho da biblioteca do cppunit, se você não esta utilizando o g++ como compilador e linker, lembre-se de atualizar as variáveis CC e LINK.

Tags: , , , ,

14 May 08 Test Infected to the bones – tornando os testes mais divertidos

Infinitest

Uma das coisas mais difíceis em introduzir a idéia do TDD é fazer com que os outros programadores da equipe realmente utilizem os testes, e para tornar esta árdua tarefa um pouco mais fácil, é necessário muitos discursos, e se possível, tornar isto um pouco mais divertido.
O Ruby, tem o autotest para isto, que sempre que uma classe ou um teste é alterado, roda apenas os testes que sofrem alguma influência desta alteração (outro dia eu escrevo sobre o autotest, mas o foco deste post é Java).
Para Java eu não conhecia nenhuma ferramenta parecida, mas acabei de encontrar o Infinitest, uma ferramenta para Java que faz praticamente a mesma coisa que o AutoTest do Ruby, mas é um pouco menos flexível, pois os indicativos Verde/Vermelho aparecem na tela dele, e não de uma forma customizável como o Autotest, mas nem por isto deixa de ser útil, é só deixar o programa aberto enquanto desenvolve, quando uma classe é alterada, ele executa o teste correspondente, e fica avisando quantos testes estão quebrados e quantos ja passaram, com os clássicos sinais verde e vermelho avisando se o trabalho ja terminou :D

Ele funciona muito bem integrado com qualquer IDE, no eclipse por exemplo, basta adicionar o infinitest.jar no classpath do projeto a mandar executar a classe: org.infinitest.Infinitest
Uma tela parecida com esta vai ficar aberta enquanto você desenvolve:


É só alterar qualquer classe Java, que os testes afetados por ela vão rodar novamente, ou então alterar um teste, que apenas ele é executado novamente.

Quando algum teste falha, aparece na area branca da tela o nome da classe de testes, o método e a linha da falha, e a barra da parte inferior da janela fica vermelha :D

O Infinitest funciona com Java + JUnit, ou seja, nada de easyb pelo menos por enquanto :(

Acho que vou fazer um plugin pro infinitest pra usar o Snarl também, como este do Autotest do ruby :D

Bom, acho que era isto, testem o Infinitest, vocês vão achar bem divertido :D

Tags: ,