Exercício – Corrigir uma falha de teste
Neste ponto, você tem uma maneira de executar testes de unidade à medida que as alterações avançam pelo pipeline de build. Você também tem uma maneira de medir a quantidade de código que é coberta pelos seus testes.
É sempre uma boa ideia executar seus testes localmente antes de enviar as alterações ao pipeline. No entanto, o que acontece quando alguém esquece e envia uma alteração que interrompe o build?
Nesta unidade, você corrigirá um build quebrado causado por um teste de unidade com falha. Aqui, você vai:
- Obtenha o código inicial do GitHub.
- Adicione ferramentas de cobertura de código ao seu projeto.
- Enviar o código por push para o seu repositório.
- Assistir ao pipeline ser executado automaticamente e os testes de unidade falharem.
- Reproduzir a falha localmente.
- Analisar e corrigir a falha.
- Enviar uma correção por push e assistir à compilação ser bem-sucedida.
Examinar o novo teste de unidade
O recurso mais recente da equipe envolve o placar de líderes. Precisamos obter o número de pontuações do banco de dados, para que possamos gravar um teste de unidade para verificar o método IDocumentDBRepository<T>.GetItemsAsync
.
O teste é como mostrado a seguir. Não é necessário adicionar nenhum código ainda.
[TestCase(0, ExpectedResult=0)]
[TestCase(1, ExpectedResult=1)]
[TestCase(10, ExpectedResult=10)]
public int ReturnRequestedCount(int count)
{
const int PAGE = 0; // take the first page of results
// Fetch the scores.
Task<IEnumerable<Score>> scoresTask = _scoreRepository.GetItemsAsync(
score => true, // return all scores
score => 1, // we don't care about the order
PAGE,
count // fetch this number of results
);
IEnumerable<Score> scores = scoresTask.Result;
// Verify that we received the specified number of items.
return scores.Count();
}
Lembre-se de que, em um teste NUnit, TestCase
fornece dados embutidos para usar esse método de teste. A NUnit chama o método de teste de unidade ReturnRequestedCount
como este:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
Este teste também usa a propriedade ExpectedResult
para simplificar o código de teste e ajudar a esclarecer sua intenção. A NUnit compara automaticamente o valor retornado com relação ao valor dessa propriedade, eliminando a necessidade de chamar explicitamente a asserção.
Escolheremos alguns valores que representam consultas típicas. Também incluiremos 0 para cobrir esse caso de borda.
Buscar o branch do GitHub
Como você fez anteriormente, busque o branch failed-test
do GitHub e faça check-out (ou alterne para) esse branch.
No Visual Studio Code, abra o terminal integrado.
Execute os seguintes comandos
git fetch
egit checkout
para baixar um branch chamadofailed-test
do repositório da Microsoft e mudar para esse branch:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
Demos ao branch o nome
failed-test
para fins de aprendizado. Na prática, você nomearia um branch após sua finalidade ou recurso.Execute estes comandos para criar um arquivo de manifesto da ferramenta local, instale a ferramenta
ReportGenerator
e adicione o pacotecoverlet.msbuild
ao seu projeto de testes:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Esta etapa é necessária porque a ramificação
failed-test
não contém o trabalho que você adicionou à ramificaçãounit-tests
.Adicione o arquivo de projeto de teste e o arquivo de manifesto da ferramenta ao índice de preparo e faça commit das alterações.
git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git add .config/dotnet-tools.json git commit -m "Configure code coverage tests"
Execute o seguinte comando
git push
para fazer upload do branchfailed-test
para seu repositório GitHub:git push origin failed-test
Veja a falha de teste do pipeline
Digamos que você estava com pressa e pressionou seu trabalho sem executar os testes uma última vez. Felizmente, o pipeline pode ajudar a capturar problemas no início quando há testes de unidade. Você pode ver isso aqui.
No Azure Pipelines, rastreie o build conforme ele é executado pelo pipeline.
Expanda a tarefa Executar testes de unidade – Versão enquanto ela é executada.
Você verá que o método de teste
ReturnRequestedCount
falha.O teste é aprovado quando o valor de entrada é 0, mas é reprovado quando o valor de entrada é 1 ou 10.
O build é publicado para o pipeline somente quando a tarefa anterior é bem-sucedida. Aqui, o build não foi publicado porque os testes de unidade falharam. Isso impede que outras pessoas acidentalmente obtenham um build danificado.
Na prática, você nem sempre vai rastrear manualmente o build enquanto ele é executado. Veja algumas maneiras de descobrir a falha:
Uma notificação por email do Azure DevOps
Você pode configurar o Azure DevOps para enviar uma notificação por email quando o build for concluído. A linha do assunto começa com "[Falha no build]" quando o build falha.
Azure Test Plans
No Azure DevOps, selecione Test Plans e Runs. Você verá as execuções de testes recentes, incluindo aquelas que acabaram de ser executadas. Selecione o teste completo mais recente. Você vê que dois dos oito testes falharam.
O painel
No Azure DevOps, selecione Overview e Dashboards. Você verá que a falha aparece no widget Tendência dos Resultados de Teste. O widget de Cobertura de Código está em branco, o que indica que a cobertura não foi executada.
A notificação de build
Embora o branch
failed-test
não inclua a notificação de build no arquivo README.md, isto é o que você veria no GitHub em caso de falha do build:
Analisar a falha de teste
Quando os testes de unidade são reprovados, você normalmente tem duas opções, dependendo da natureza da falha:
- Se o teste revelar um defeito no código, corrija o código e execute os testes novamente.
- Se a funcionalidade mudar, ajuste o teste de acordo com os novos requisitos.
Reproduzir a falha localmente
Nesta seção, você reproduzirá a falha localmente.
No Visual Studio Code, abra o terminal integrado.
No terminal, execute este comando
dotnet build
para compilar o aplicativo:dotnet build --configuration Release
No terminal, execute este comando
dotnet test
para executar os testes de unidade:dotnet test --no-build --configuration Release
Você deverá ver os mesmos erros que viu no pipeline. Aqui está a parte da saída:
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Failed ReturnRequestedCount(1) [33 ms] Error Message: Expected: 1 But was: 0 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed ReturnRequestedCount(10) [1 ms] Error Message: Expected: 10 But was: 9 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed! - Failed: 2, Passed: 6, Skipped: 0, Total: 8, Duration: 98 ms
Encontrar a causa do erro
Você percebe que cada teste com falha produz um resultado com diferença de um. Por exemplo, quando 10 é esperado, o teste retorna 9.
Dê uma olhada no código-fonte do método que está sendo testado, LocalDocumentDBRepository<T>.GetItemsAsync
. Você deve ver isto:
public Task<IEnumerable<T>> GetItemsAsync(
Func<T, bool> queryPredicate,
Func<T, int> orderDescendingPredicate,
int page = 1, int pageSize = 10
)
{
var result = _items
.Where(queryPredicate) // filter
.OrderByDescending(orderDescendingPredicate) // sort
.Skip(page * pageSize) // find page
.Take(pageSize - 1); // take items
return Task<IEnumerable<T>>.FromResult(result);
}
Nesse cenário, você pode verificar o GitHub para ver se o arquivo foi alterado recentemente.
Você suspeita que pageSize - 1
está retornando um resultado a menos e que isso deve ser apenas pageSize
. Em nosso cenário, este é um erro que você cometeu ao enviar por push o trabalho sem teste, mas em um cenário real, você pode verificar com o desenvolvedor que alterou o arquivo no GitHub para determinar o motivo da alteração.
Dica
Discussão e colaboração também podem ocorrer no GitHub. Você pode comentar sobre uma solicitação de pull ou abrir um problema.
Corrigir o erro
Nesta seção, você corrigirá o erro alterando o código de volta para seu estado original e executando os testes para verificar a correção.
No Visual Studio Code, abra Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs no Explorador de Arquivos.
Modifique o método
GetItemsAsync
, conforme mostrado aqui:public Task<IEnumerable<T>> GetItemsAsync( Func<T, bool> queryPredicate, Func<T, int> orderDescendingPredicate, int page = 1, int pageSize = 10 ) { var result = _items .Where(queryPredicate) // filter .OrderByDescending(orderDescendingPredicate) // sort .Skip(page * pageSize) // find page .Take(pageSize); // take items return Task<IEnumerable<T>>.FromResult(result); }
Esta versão muda
pageSize - 1
parapageSize
.Salve o arquivo.
No terminal integrado, compile o aplicativo.
dotnet build --configuration Release
Você deverá ver o build ser executado com sucesso.
Na prática, você pode executar o aplicativo e testá-lo rapidamente. Para fins de aprendizado, vamos ignorar isso por enquanto.
No terminal, execute os testes de unidade.
dotnet test --no-build --configuration Release
Você verá que os testes são aprovados.
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Passed! - Failed: 0, Passed: 8, Skipped: 0, Total: 8, Duration: 69 ms
No terminal integrado, adicione cada arquivo modificado ao índice, faça commit das alterações e efetue push do branch para o GitHub.
git add . git commit -m "Return correct number of items" git push origin failed-test
Dica
O ponto (
.
) neste exemplogit add
é um caractere curinga. Ele corresponde a todos os arquivos não preparados no diretório atual e em todos os subdiretórios.Antes de usar esse caractere curinga, é uma boa prática executar
git status
antes de se comprometer a garantir que você está preparando os arquivos que pretende preparar.Retornar para o Azure Pipelines. Inspecione a alteração mover-se pelo pipeline. Os testes são aprovados e o build geral é bem-sucedido.
Opcionalmente, para verificar os resultados dos testes, você pode selecionar as guias Tests e Code Coverage quando o build for concluído.
Você também pode conferir o painel para ver a tendência de resultados atualizada.
Ótimo! Você corrigiu o build. Em seguida, você aprenderá a limpar seu ambiente do Azure DevOps.