Quando trabalho com node ou com dnx eu costumo ter alguma ação de autotest rodando em background para os testes de unidade. Autotest é um conceito que já não é novo, e eu me lembro de ter conhecido ele lá atrás quando comecei a trabalhar com Ruby. Até onde sei, foi onde ele se popularizou, imagino que tenha surgido em alguma linguagem obscura, ou que eu não tenha tanta familiaridade.

Desde então sempre busco trabalhar com algum tipo de rotina de testes rodando o tempo todo. No node é muito comum fazer isso com o nodemon. Pra quem trabalha com .NET, o Visual Studio traz a capacidade de rodar testes após um build de forma automática (menu Test > Test Settings > Run Tests After Build), e outras ferramentas fazem teste continuamente, como o NCrunch e o Alive (mas esse é outro assunto, ainda que parecido).

Rodando testes após a build com o Visual Studio

Mas eu sou do mundo da linha de comando, e fiquei feliz quando o dnx trouxe o comando “dnx-watch” (que vai morrer ser substituído, e provavelmente vai virar “dotnet watch”, mais informações sobre isso aqui nesse outro post). Com ele, podemos criar um projeto de testes, ir até o diretório, e rodar “dnx-watch test”, e sempre que algum código .cs for alterado ele roda os testes novamente, nem precisa compilar uma dll.

No entanto, ainda falta um pouco para o dnx .NET Core se estabelecer, ele ainda nem está pronto, e só teremos sua conclusão até o fim do ano (ainda sem data específica). Diversos outros projetos vão demorar um pouco pra migrar. Enquanto isso, eu quero ter uma janela de terminal aberta em um dos meus 3 monitores, rodando testes continuamente. E o projeto open source que eu mais contribuo, o CodeCracker, não é um projeto .NET Core ainda (ainda esperamos toda a definição do .NET Core, para então migrar).

Eu não podia ficar sem autotest nesse tipo de projeto. Assim, fiz um script que observava a alteração da dll de testes, e rodava os testes. Era um script powershell, e até o Windows 8 ele funcionava bem. Você pode vê-lo no projeto do CodeCracker, nessa versão inicial, aqui. A parte boa desse script é que, como o framework de testes é o XUnit, eu posso indicar qual classe de teste eu quero rodar para o script, e isso torna tudo mais rápido, já que o CodeCracker tem quase dois mil testes de unidade, e demora mais segundos do que eu gosto de esperar pra terminar uma execução.

O interessante é que para fazer ele funcionar com Powershell, eu não podia manter a console rodando, eu tinha que rodar o script, terminar, e deixar um watch aberto, por causa de características do Powershell e conflitos com o file system watcher. Isso causava um comportamento estranho, onde o script jogava texto na tela, mas você ainda tinha controle do terminal. Mas ele fazia o scroll da tela direitinho, e quando você digitava, era sempre após o texto que o test runner produziu. Mega gambiarra, mas funcionava; e como ainda era algo só pra rodar os testes na minha própria máquina, eu aturava a gambiarra. E eu ainda tinha que compilar, não chegava a ser como o dnx-watch, eu ainda tinha que gerar uma dll, mas já era bem prático.

Quando o Windows 10 chegou, esse comportamento mudou, imagino que por causa das diversas evoluções nas janelas de terminal do Windows 10, e do Powershell em si, que ganhou o PSReadline (lindo!) nativamente. O script ainda jogava o texto do resultado dos testes na tela, mas ao digitar no terminal o cursor ainda estava no mesmo lugar, ou seja, um monte de texto de saída dos testes se misturava com o que eu digitava. E quando os testes rodavam várias vezes seguidas, com frequência a saída se sobrepunha. Isso me obrigava a, sempre que compilava, voltar para o terminal e limpar a tela com “cls”. Um saco.

Me lembrei recentemente, quando pareava com o Igor Abade, construindo meu primeiro módulo de Powershell, do nodemon. É uma ferramenta de node que reinicia uma aplicação node quando algum arquivo muda (um .js, .ts, .coffee, ou o qualquer padrão que você quiser). Ele é muito usado para autotest, e também para reiniciar uma aplicação que acaba de ser alterada, por exemplo, é super prático. Lembrei que o nodemon era capaz de rodar comandos arbitrários, e tentei fazer ele rodar com o Pester, o runner/framework do Powershell mais usado e que estava no meu projeto. Consegui. O resultado está aqui no Github, no projeto Posh-Alias. É basicamente esta linha:

nodemon --ext "ps1,psd1,psm1" --exec "powershell -command invoke-pester -EnableExit"

Em poucas palavras, o que ela faz é rodar o nodemon observando as extensões do powershell (.ps1, .psd1 e .psm1), e, quando algum arquivo com essas extensões mudar, rodar o comando especificado no parâmetro “exec”, que é o powershell em si. Esse comando powershell é o Invoke-Pester, que roda os testes, com a opção -EnableExit do Pester, que vai usar um exit code, usado pelo nodemon para saber se os testes passaram (exit 0) ou falharam (qualquer outro número de saída). Ficou excelente, eu trabalhava nos arquivos de powershell, e ao salvar os testes executavam. Olhem como ficou (clique para ampliar):

Autotest de .NET rodando com nodemon

Experimente você também. Clone o repositório, instale o node e o nodemon, e rode o comando acima. O nodejs você baixa aqui (peque a versão 4 ou a 5), e para instalar o nodemon basta rodar “npm install -g nodemon”.

Assim que terminei de fazer isso no Posh-Alias, lembrei do CodeCracker. Fui lá e atualizei o script. A última versão, que é a que está na master, está aqui. Ficou bem melhor, e resolveu todos os problemas. Agora, basta eu rodar o script e deixar ele rodando os testes. Não preciso mais voltar no terminal e ficar limpando a tela, e a saída é limpa. A execução ficou um pouco diferente, em vez de observar as extensões, eu observo especificamente a dll de testes, e na hora de rodar, em vez de rodar o Powershell e o Pester, eu rodo o XUnit. E a funcionalidade do script, de rodar apenas uma classe de testes, foi facilmente mantida.

O que você achou? Que tal experimentar no seu projeto? Ele nem precisa ser .NET, pode ser Python, Ruby, Java, o que for. E se for Node, melhor ainda, já que o nodemon vem de lá, e entende o ambiente de forma nativa.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.