Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Wilson Batista

Teste unitários

Recommended Posts

Ola pessoal


To estudando teste unitário e sei que são essências para a qualidade do funcionamento do sistema, estou numa fase de adaptação (digamos assim), espero que vocês me ajudem nas seguintes dúvidas a seguir:


1 Sempre e toda vez que eu fizer uma classe nova, é bom fazer teste unitário nelas?

2 Quando eu fizer um teste unitário numa classe, tenho que testar todas as possibilidades de valores na sua API?

3 Aproveitando o que seria TDD?


Estou usando phpunit para fazer os testes

Compartilhar este post


Link para o post
Compartilhar em outros sites

1 Sempre e toda vez que eu fizer uma classe nova, é bom fazer teste unitário nelas?

Depende. Em classes muito triviais, eu considero um desperdício criar casos de teste.

2 Quando eu fizer um teste unitário numa classe, tenho que testar todas as possibilidades de valores na sua API?

Isso é impossível! Muitas vezes o domínio da função é infinito.

Você deve testar principalmente os casos de fronteira do domínio e alguns casos gerais.

 

Imagine que você vai construir uma função fatorial. O domínio da função é [inline]{x real, x >= 0}[/inline], tal que [inline]0! = 1[/inline] por definição. Preocupe-se principalmente com a fronteira desse domínio:

class FactorialTest extends PHPUnit_Framework_TestCase {
    public function testSomeFactorials() {
        $this->assertEquals(6, factorial(3));
        $this->assertEquals(24, factorial(4));
        $this->assertEquals(120, factorial(5));
    }

    public function testFactorial0Returns1() {
        $this->assertEquals(1, factorial(0));
    }

    public function testFactorial1Returns1() {
        $this->assertEquals(1, factorial(1));
    }

    public function testFactorialOfNegativeNumbersThrowException() {
        try {
           factorial(-1);
           $this->fail('Factorial function with negative argument should not return');
        } catch (DomainException $e) {
           // pass
        }
    }
}

3 Aproveitando o que seria TDD?

http://pt.wikipedia.org/wiki/Test_Driven_Development

Compartilhar este post


Link para o post
Compartilhar em outros sites

valew henrique

Imagine que você vai construir uma função fatorial. O domínio da função é {x real, x >= 0}, tal que 0! = 1 por definição. Preocupe-se principalmente com a fronteira desse domínio:

Não entendi o que você quis dizer com: [inline]0! = 1[/inline] , você quis dizer que 0 é diferente de 1 no domínio da função ??

 

Fronteira desse domínio, seria o retorno obvio de todos os métodos?? exemplo no código fatorial acima, sei que o valores retornados nunca será abaixo de 0, isso seria a fronteira do domínio?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fronteira desse domínio, seria o retorno obvio de todos os métodos?? exemplo no código fatorial acima, sei que o valores retornados nunca será abaixo de 0, isso seria a fronteira do domínio?

Nesse exemplo sim, a fronteira é o 0, mas também há casos onde a fronteira do domínio é infinita também. O que você tem a fazer é identificar "grupos" de fronteira e ter ao menos um teste para cada grupo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

1 Sempre e toda vez que eu fizer uma classe nova, é bom fazer teste unitário nelas?

 

Discordo um pouco do Henrique aqui, acho que até mesmo classes muito simples precisam ser testadas. Se você não testar como ter certeza que funciona? As vezes até um pequeno erro de sintase escapa a verificação do IDE ou outra coisa tola. Então é bom testar sempre.

 

 

2 Quando eu fizer um teste unitário numa classe, tenho que testar todas as possibilidades de valores na sua API?

 

Além do tipo que a classe deve aceitar e das condições limítrofes do mesmo. Eu costumo testar todos os tipos primitivos, e pelo menos um tipo de objeto fictício que ela não deve aceitar.

 

Pode-se entender, por exemplo, o um ou zero como true ou falso quando não se deveria o que pode gerar bugs. A unica ressalva é que o teste deve permanecer simples se aumentar muito a complexidade ha algum problema com o teste ou com a classe.

 

Geralmente minhas classes tem dois testes e dois providers, um para os casos ok e outro para as Execeptions.

 

 

3 Aproveitando o que seria TDD?

 

 

O melhor jeito de TDD que se adaptou a mim é aquele em que o teste e a classe crescem juntos. Sempre primeiro adicionando a funcionalidade no teste fazendo o falhar e em seguida adicionando o código da classe e fazendo passar.

 

O desenvolvimento corre no ciclo de edição do teste -> execução do fail do teste -> edição da classe -> execução com sucesso do teste e cada ciclo deste não deve demorar mais que uns 30 ~60 segundos. O código do teste e da classe crescem assim juntos em colunas lado a lado.

 

Acho muito massante ter de escrever o teste inteiro antes da classe além do que depois ter te resolver todos aqueles fails é algo que ja me coloca alguma inercia. Outra dica disso é nunca deixar um teste fail para ser corrigido depois. Do jeito acima é dinâmico e você sente o trabalho evoluindo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Discordo um pouco do Henrique aqui, acho que até mesmo classes muito simples precisam ser testadas. Se você não testar como ter certeza que funciona? As vezes até um pequeno erro de sintase escapa a verificação do IDE ou outra coisa tola. Então é bom testar sempre.

Erros de sintaxe não são como bugs, pois aqueles são determinísticos, você sabe quando ele ocorre e qual a causa. Eu realmente acho um desperdício de tempo testar setters e getters que não possuam regras especiais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Henrique, imagine a situação hipotética que por algum motivo um programador antes do feriado de natal revisa todos os códigos e testes de seus clientes e se certifica que tudo esta dentro dos conformes para que ele possa viajar tranquilo no feriado.

 

Anteriormente em uma edição trivial ele esqueceu o ponto virgula em uma linha de uma classe que por acaso só é executada no natal e em sua véspera, como a classe é muito simples ele não a cobriu com um teste e logo não percebeu este erro. Quando voltar de sua viajem esse sujeito vai se deparar com emails e mensagens na secretária de clientes furiosos dizendo que seus e-commerces não funcionaram no momento mais importante do ano.

 

Isso poderia ser evitado com um simples "testInstance()" que leva cerca de um minuto para ser criado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma rápida explicação dos providers aqui neste link. Basicamente eles permitem repetir o mesmo teste com dados diferentes.

 

A classe abaixo aceita um cep apenas como string no formato "xxxxx-xxx" onde x é um numero inteiro de 0 a 9.

class ZipCodeBr
{

    protected $zipCode;

    public function __construct($zipCode)
    {
        if (\preg_match('/^(\d){5}-(\d){3}$/', $zipCode)) {
            $this->zipCode = $zipCode;
            return;
        }
        throw new \Exception('O CEP não esta em um formato válido');
    }

    public function getZipCode()
    {
        return $this->zipCode;
    }

}

agora o teste

 

class ZipCodeBrTest extends PHPUnit_Framework_TestCase
{
    public function testInstance()
    {
        $zipCode = new ZipCodeBr('01021-200');
        $this->assertEquals('01021-200', $zipCode->getZipCode());
    }
    
    public function providerException()
    {
        return array(
            array(null),
            array(true),
            array(false),
            array(01021-200),
            array('string'),
            array('01021200'),
            array('01.021-200'),
            array('0121.200'),
            array(0121.200),
        );
    }
    
    /**
     * @dataProvider providerException
     */
    public function testException($data)
    {
        try{
            $zipCode = new ZipCodeBr($data);
        } catch (\Exception $ex) {
            return;
        }
        $this->fail();
    }
}

 

Note que método testException() recebe os dados fornecidos pelo array do provider, no caso como temos 9 arrays o teste será repetido 9 vezes, uma para cada array.

 

Espera-se que ao tentar instanciar um objeto ZipCodeBr com qualquer valor deste provider seja lançada uma exceção e quando ela é lançada a capturamos com o catch e simplesmente damos um return de maneira que a linha $this->fail(); não seja executada. Se a exceção não é lançada então não ocorre o return e o teste falha.

 

Esta é a minha maneira preferida de testar exceções, mas exitem outras. Leia no manual.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Henrique, imagine a situação hipotética que por algum motivo um programador antes do feriado de natal revisa todos os códigos e testes de seus clientes e se certifica que tudo esta dentro dos conformes para que ele possa viajar tranquilo no feriado.

Syntax checker está aí pra isso ;]

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.