Priorizando testes com PHPUnit

Conforme nossa suíte de testes vai crescendo, obviamente, nossos testes vão demorando cada vez mais a finalizar e gerar nossas métricas. E o maior problema para muitos, é quando os testes que falham, estão “no final” da suíte.

Mas, seguindo a risca o TDD, não podemos definir a ordem dos testes, correto? Mas e se pudéssemos fazer os testes que falharam, rodassem primeiro? E é isso que o plugin Clever and Smart faz para nós.

A instação, vamos utilizar o Composer, nosso velho conhecido:

composer require "lstrojny/phpunit-clever-and-smart" "0.*"

A configuração é simples, ele depende basicamente da extensão SQLite3 instalada e habilitada - não, eu não vou te ensinar a fazer isso aqui nesse texto. Bastando apenas adicionar o nó abaixo em seu phpunit.xml:

<listeners>
        <listener class="PHPUnit\Runner\CleverAndSmart\TestListener">
            <arguments>
                <object class="PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage">
                    <arguments>
                        <string>./data/phpunit-cas.db</string>
                    </arguments>
                </object>
            </arguments>
        </listener>
    </listeners>
</listener>

Você só precisa alterar o caminho do banco SQlite que será criado para registrar os testes. Experimente fazer um teste falhar ao rodar a suíte e depois tente rodar novamente, você verá que os testes que falharam, rodarão primeiro ;)

Para mim, esse plugin agilizou e muito o processo de teste das aplicações que mantenho, espero que seja útil pra você também.

Rodando testes unitários em paralelo

Comecei a utilizar o plugin paratest em meus testes unitários para rodar testes em paralelo utilizando vários processos. Isso agiliza em muito o processo de testes - isso se você tiver uma máquina multi-core claro.

composer.phar require "brianium/paratest" "dev-master"

Somente isso já basta para rodar seus testes. Voce pode simplesmente rodar:

./vendor/bin/paratest

O paratest utiliza o mesmo arquivo de configuração do PHPUnit (phpunit.xml) para efetuar o bootstrap então, tecnicamente, você não verá muitas mudanças. Mas é possível obter algumas novas opções mais úteis ao dia-a-dia, e pra mim, a mais importante:

  • –processes (-p): o número de processos que vocÊ deseja rodar paralelamente, o padrão é 5.

Em resumo, o Paratest é um ótimo utilitário para agilizar seus testes, e os únicos problemas que tive alguns testes foram com o plugin Clever and Smart (esse é papo para outro post) por conta do SQLite.

Load Balance com Nginx

Para fazer um simples load balance com Nginx é simples.

Primeiro, vamos definir a máquina que ficará na frente e receberá todas as requisições e encaminhará para nosso parque de máquinas.

Começando pelo /etc/nginx/nginx.conf para habilitar algumas coisas, como
os tokens. Assim, cada máquina terá uma “identidade única” para a requisição que receber.

http {
    ...
    server_tokens on;
    server_names_hash_bucket_size 64;
    server_name_in_redirect off;
    ...
}

Com isso, vamos pegar nosso arquivo de host virtual e inserir as máquinas que fazem parte do nosso parque e poderão receber os clientes. Abaixo, mostro o conteúdo de exemplo do arquivo /etc/nginx/sites-enabled/default:

upstream nodes {
    ip_hash;

    server *IP_SLAVE_1*:*PORT_SLAVE_1* max_fails=3 fail_timeout=30s;
    server *IP_SLAVE_2*:*PORT_SLAVE_2* max_fails=3 fail_timeout=30s;
    server *IP_SLAVE_3*:*PORT_SLAVE_3* max_fails=3 fail_timeout=30s;
    ...
}

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    location / {
        # Sending to other servers
        proxy_pass http://nodes;
        proxy_pass_request_headers on;
        proxy_set_header Host $http_host;
    }
    ...
}

Na sessão upstream_nodes é onde inserimos nossa máquina. Você pode simplesmente colocar os IPs das máquinas que compõem o parque, com algumas opções para que o Nginx não espere eternamente uma conexão de uma máquina que possa estar fora.

A opção ip_hash é onde cria o identificador da máquina, algo como o que falei acima sobre os tokens.

Pronto, agora basta restartar o Nginx e começar a configurar suas máquinas que receberão as requisições normalmente com o ambiente e servidor web que for de sua escolha.