Exercício – Corrigir um teste com falhas
Neste ponto, tem uma forma de executar testes de unidades à medida que as alterações são processadas através do pipeline de compilação. Tem também uma forma de avaliar a quantidade de código que é abrangido pelos seus testes.
É sempre uma boa ideia executar os testes localmente antes de submeter alterações no pipeline. Mas o que acontece quando alguém se esquece e submete uma alteração que interrompe o funcionamento da compilação?
Nesta unidade, você corrigirá uma compilação quebrada causada por um teste de unidade com falha. Neste exercício, irá:
- Obtenha o código inicial do GitHub.
- Adicione ferramentas de cobertura de código ao seu projeto.
- Emitir o código para o seu repositório.
- Ver o pipeline a ser executado automaticamente e os testes de unidades a falharem.
- Reproduzir a falha localmente.
- Analisar e corrigir a falha.
- Emitir uma correção e ver a compilação a ser bem-sucedida.
Rever o novo teste de unidades
A mais recente característica da equipa envolve a tabela de classificação. Precisamos obter o número de pontuações do banco de dados, para que possamos escrever um teste de unidade para verificar o IDocumentDBRepository<T>.GetItemsAsync
método.
Veja a seguir o aspeto do teste. Você não precisa 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, num teste NUnit, TestCase
fornece os dados inline que servem para testar esse método. O NUnit chama o método de teste de unidades ReturnRequestedCount
da seguinte forma:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
Este teste também utiliza a propriedade ExpectedResult
para simplificar o código de teste e clarificar a sua intenção. O NUnit compara automaticamente o valor de retorno com o valor desta propriedade e elimina, assim, a necessidade de chamar explicitamente a asserção.
Escolheremos alguns valores que representam consultas típicas. Também incluiremos 0 para cobrir essa caixa de borda.
Obter o ramo do GitHub
Como você fez anteriormente, busque a failed-test
ramificação no GitHub e faça check-out (ou mude para) essa ramificação.
No Visual Studio Code, abra o terminal integrado.
Execute o seguinte
git fetch
e comandos para baixar uma ramificação nomeadafailed-test
do repositório da Microsoft egit checkout
alternar para essa ramificação:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
Nomeamos o ramo
failed-test
para fins de aprendizagem. Na prática, você nomearia uma filial de acordo com sua finalidade ou característica.Execute estes comandos para criar um arquivo de manifesto da ferramenta local, instalar a
ReportGenerator
ferramenta e adicionar ocoverlet.msbuild
pacote ao seu projeto de testes:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Você precisa desta etapa porque a
failed-test
ramificação não contém o trabalho que você adicionou àunit-tests
ramificação.Adicione o arquivo de projeto de teste e o arquivo de manifesto da ferramenta ao índice de preparo e confirme as 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
git push
comando para carregar afailed-test
ramificação no repositório GitHub:git push origin failed-test
Ver o teste com falha no pipeline
Digamos que você estava com pressa e empurrou seu trabalho sem executar os testes uma última vez. Felizmente, o pipeline pode ajudá-lo a detetar problemas precocemente quando há testes de unidade. Você pode ver isso aqui.
No Azure Pipelines, rastreie a compilação à medida que ela é executada pelo pipeline.
Expanda a tarefa Executar testes de unidades – Versão à medida que é executada.
Vai constatar que o método de teste
ReturnRequestedCount
falha.O teste passa quando o valor de entrada é 0, mas falha quando o valor de entrada é 1 ou 10.
A compilação é publicada no pipeline apenas quando a tarefa anterior for bem-sucedida. Aqui, a compilação não foi publicada porque os testes de unidade falharam. Este procedimento impede que outras pessoas obtenham acidentalmente uma compilação que deixou de funcionar.
Na prática, nem sempre vai rastrear manualmente a compilação enquanto é executada. Aqui estão 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 a compilação for concluída. O assunto da mensagem começa por “[Falha na compilação]” quando a compilação falhar.
Planos de teste do Azure
No Azure DevOps, selecione Planos de Teste e, em seguida, selecione Execuções. Vê as execuções de testes recentes, incluindo a que acabou de ser executada. Selecione o teste concluído mais recente. Você vê que dois dos oito testes falharam.
O painel
No Azure DevOps, selecione Visão geral e, em seguida, selecione Painéis. Verá a falha a aparecer no widget Tendência dos Resultados dos Testes. O widget Cobertura de código está em branco, o que indica que a cobertura de código não foi executada.
O selo de construção
Embora a ramificação não inclua o selo de compilação no arquivo README.md, aqui está o que você veria no GitHub quando a
failed-test
compilação falhar:
Analisar a falha do teste
Quando os testes de unidade falham, normalmente você tem duas opções, dependendo da natureza da falha:
- Se o teste revelar um defeito no código, corrija o código e execute novamente os testes.
- Se a funcionalidade mudar, ajuste o teste para corresponder aos 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
dotnet build
comando para construir o aplicativo:dotnet build --configuration Release
No terminal, execute este
dotnet test
comando para executar os testes de unidade:dotnet test --no-build --configuration Release
Você deve ver os mesmos erros que viu no pipeline. Aqui está 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
Descobrir a causa do erro
Você percebe que cada teste reprovado produz um resultado que está desligado por um. Por exemplo, quando se espera o valor 10, o teste devolve um 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 está retornando um resultado a menos e que pageSize - 1
isso deveria ser apenas pageSize
. Em nosso cenário, esse é um erro que você cometeu quando enviou o trabalho sem teste, mas em um cenário do mundo real, você pode verificar com o desenvolvedor que alterou o arquivo no GitHub para determinar o motivo da alteração.
Gorjeta
O GitHub também funciona como um local de discussão e colaboração. Pode comentar um pedido Pull ou abrir um problema.
Corrigir o erro
Nesta seção, você corrigirá o erro alterando o código de volta ao 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
GetItemsAsync
método como 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 é alterada de
pageSize - 1
parapageSize
.Guarde o ficheiro.
No terminal integrado, construa o aplicativo.
dotnet build --configuration Release
Você deve ver que a compilação é bem-sucedida.
Na prática, você pode executar o aplicativo e experimentá-lo brevemente. Para fins de aprendizagem, vamos pular isso por enquanto.
No terminal, execute os testes de unidade.
dotnet test --no-build --configuration Release
Verifica que os testes são bem-sucedidos.
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, confirme as alterações e envie a ramificação para o GitHub.
git add . git commit -m "Return correct number of items" git push origin failed-test
Gorjeta
O ponto (
.
) nestegit add
exemplo é um caractere curinga. Corresponde a todos os ficheiros 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 para garantir que você esteja preparando os arquivos que pretende preparar.Volte ao Azure Pipelines. Veja a alteração mover-se através do pipeline. Os testes são aprovados e a compilação geral é bem-sucedida.
Opcionalmente, para verificar os resultados do teste, você pode selecionar as guias Testes e Cobertura de código quando a compilação for concluída.
Você também pode conferir o painel para visualizar a tendência de resultados atualizados.
Excelente! Você corrigiu a compilação. Em seguida, você aprenderá como limpar seu ambiente de DevOps do Azure.