Utilitários de teste 2

Posted by Adam Brandizzi Thu, 20 May 2010 13:15:00 GMT

E-Plamtax foi um projeto muito positivo que executamos para a Força Aérea. A equipe do E-Plamtax aprendeu muitas coisas no projeto, mas muitas dessas aprendizagens ficaram guardadas conosco. Uma das mais interessantes é a criação de utilitários de teste.

Utilitários de teste são uma maneira de reaproveitar código em testes unitários. Usualmente, isso é feito utilizando os métodos setUp ou @Before dos casos de teste, mas isso tem algumas desvantagens. Por exemplo, em um caso de teste, podemos ter a seguinte inicialização:

    private Address address;
    private AddressDAO addressDAO;
    
    @Before
    public void setUp() {
        address = new Address();
        address.setStreet("Rua fulano");
        address.setNumber("123/A");
        addressDAO = new AddressDAO();
    }

Se tivermos um teste com o abaixo essa inicialização funciona bem…

    @Test
    public void testGetAllAddresses(){
        addressDAO.addAddress(address);
        
        List<Address> addresses = addressDAO.getAllAddresses();
        
        assertEquals(1, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber());
    } 

Agora, se tivermos o teste abaixo, o objeto criado é desperdiçado:

    @Test
    public void testGetNoAddress() {
        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(0, addresses.size());
    }
 

Se o código for como o seguinte, teremos redundância de código. também temos de decidir SE o outro objeto deve ser criado no @Before também ou no método.

    @Test
    public void testGetAllAddressesMoreThanOne() {
        addressDAO.addAddress(address);
        Address address2 = new Address();
        address2.setStreet("Outra rua");
        address2.setNumber("111");
        addressDAO.addAddress(address2);
        List<Address> addresses = addressDAO.getAllAddresses(); 
        assertEquals(1, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber()); 
    }

Esses inconvenientes são menores quando comparados à tarefa de criar as dependências e um objeto para o teste. Por exemplo, para testar uma classe Person que agrega um Address em um outro caso de teste, teremos de ter um @Before semelhante a esse:

    private Person person;
    private Address address;
    private PersonDAO personDAO;
        
    @Before     
    public void setUp() {
        address = new Address();
        address.setStreet("Rua fulano");
        address.setNumber("123/A");
        person = new Person();
        person.setName("João");
        person.setAddress(address);
        personDAO = new PersonDAO();
    } 

O código para a criação de endereços replicou-se, e é difícil criar as dependências. Nesses exemplos, vemos casos simples, mas é fácil visualizar como a situação irá se complicar.

Nós solucionamos esse problema criando uma classe para criar esses objetos. Essa classe seria algo como isso:

    public class TestUtil {
        public static Address utilCreateAddress(String street, String number) {
            Address address = new Address();
            address.setStreet("Rua fulano");
            address.setNumber("123/A");
            return address;     
        }
     
        public static Person utilCreatePerson(String name, Address address) {
            Person person = new Person();
            person.setName(name);
            person.setAddress(address);
            return person;
        }
    }

Nossos casos de teste estendiam a TestUtil, facilitando a criação de objetos:

public class TestAddress2 extends TestUtil {
    private AddressDAO addressDAO = new AddressDAO();

    @Test
    public void testGetAllAddresses() {
        Address address = utilCreateAddress("Rua fulano", "123/A");
        addressDAO.addAddress(address);

        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(1, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber());
    }

    @Test
    public void testGetNoAddress() {
        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(0, addresses.size());
    }

    @Test
    public void testGetAllAddressesMoreThanOne() {
        Address address = utilCreateAddress("Rua fulano", "123/A");
        Address address2 = utilCreateAddress("Outra rua", "111");
        addressDAO.addAddress(address);
        addressDAO.addAddress(address2);

        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(2, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber());
    } 
} 

Como também precisávamos frequentemente de um objeto qualquer, ou que apenas um ou outro parâmetro fosse definido, criávamos variantes dos métodos:

    public static Address utilCreateAddress() {
        return utilCreateAddress("Qualquer", "Qualquer");
    }

    public static Person utilCreatePerson() {
        return utilCreatePerson("José", utilCreateAddress());
    } 

O E-Plamtax foi um projeto um tanto complexo, com grandes redes de dependências de objetos. O uso desses utilitários de teste viabilizou a prática de TDD no sistema. Era emocionante descobrir que, para criar aquele documento que dependia de sete outros documentos e uns cinco ou seis usuários, bastava chamar um método :)

Naturalmente, há mais sobre nossos utilitários de teste do que foi escrito aqui, e pode haver mais ainda que sequer fizemos. (Por exemplo, pode ser interessante produzir utilitários de teste para classes específicas, ao invés de um gigantesco utilitário) Entretanto, como a ideia é bem simples, esperamos que esse pontapé inicial lhe motive a pensar sobre o tema. Até mais!

Sobre o I Fórum de Software Livre do COMAER

Posted by Clédiston Santos Tue, 02 Dec 2008 00:12:00 GMT

Participamos do I Fórum de Software Livre – SWL promovido pelo Centro de Computação de Aeronáutica de Brasília, muitas coisas interessante aconteceram e podemos destacar que:

1. Foi um evento muito interessante com a participação das demais forças (Exército, Marinha, PMDF). A grande participação dor organismos militares provou que o evento teve seu direcionamento para  um público bem definido e exigente. Outras instituições públicas também participaram como o SERPRO, DATAPREV, Min. Planejamento SLTI, CAIXA.

2. Muitas palestras interessantes, por exemplo, os processos de migração para SWL do Cindacta, do Comando da Aeronáutica, da Polícia Militar do DF, do SERPRO, da DATAPREV. O nível de palestras estava muito interessante, devemos sugerir que no próximo ano sejam menos paletras no mesmo dia, pois ficou muito puxado. Tive o prazer de dar uma palestra com o título “Formas de contratação em software livre”, que tinha por objetivo orientar gestores a contratar serviços de SWL através de licitações, mostrando vários modelos para isso. Segue a apresentação conforme prometido no evento.

 


3. Cases de sucesso da SEA Tecnologia sendo expostos nas palestras pelo próprios clientes. Principalmente os cases Sigadaer/Aeronática, muito falado em nosso blog, e a migração do MS-Exchange para Zimbra na Polícia Militar do DF. Foi muito gratificante ouvir nossos clientes tecendo elogios à SEA e expondo seus projetos realizados em parceria conosco.

4. A liberação do código fonte, pela Aeronáutica e pelo Exército, do código fonte do SIGADAER para o Portal do Software Público. Um passo importante para as forças armadas, pois a Aeronáutica quebra barreiras internas e no meio militar sobre abertura de código fonte mantendo a soberania de nosso país.