Você está na página 1de 24

---------------------------------------------------------

01.Promovendo rápido feedback


---------------------------------------------------------

------------------------------
Introdução
------------------------------
Como saber se seu código está funcionando?
talvez vc precise de uma pessoa dar esse feedback
E talvez esse tempo que vc dependa dela é um tempo relativamente grande
O que eu posso fazer para reduzir esse tempo?O que faço para ser mais
idenpendente dessa pessoa?
Mas será que eu fico mais confiante ao mandar o código
para essa equipe de teste?Para essa pessoa?
No curso vamos aprender técnicas para aumento de confiança
do nosso código.

Vamos começar testes automatizados primeiro com a solução console


Vamos ver o problema que isso nos traz. Depois vamos começar a trabalhar com
XUNit.Trabalhando com testes nesse framework .Aí nos vamos ficar intimos
de uma Tela do Visual Studio que chamamos de gerenciador de teste.
Se o VS estiver em ingles Test Explorer.
O teste automatico vai trazer alguns beneficios
-Vai diminuir o tempo de feedback
-Seu feedback vai ser maior, mais rápido
-Voce vai conseguir comunicar atraves de seus testes,
comunicar o comportamento do seu sistema
-A cada nova funcionalidade eu fico com medo do meu sistema quebrar
-Meu código vai poder ficar melhor, vou poder melhorar o código
pois vamos ter os testes automatizados para me apoiar nessa tarefa
Teste é um metodo de uma classe

------------------------------
O sistema de leilões
------------------------------
Se não tiver esse template de projeto instalado abra o menu Ferramentas\Extensões
e Atualizações e procure pela extensão Microsoft Visual Studio Test Platform.
Em seguida basta instalá-la ou habilitá-la.

------------------------------
Avaliando um leilão
------------------------------
Estamos prontos para implementar a primeira história juntos

Trello
Fazer ---Fazendo---Feito
Backlog--Desenvolvendo--Pronto

Como sei que a funcionalidade está funcionando?


Afinal aqui não temos um sistema visual,janela,aplicação
desktop onde eu criou alguns leiloes e faço alguns lances
e verrifico, não temos portal web
NO exemplo só temos as classe, oque fazer então?
Temos que criar um outro códigoQue vai criar um objeto tipo leilao
Alguns lances, objeto tipo lance e verificar se o lance ganhado r
é o que coloquei como exemplo lá'
++++++++
Vamos criar um projeto para guardar todos os projetos
OBS:temos a pasta src-> que é o código de negócio, produçao
e uma pasta para test-> para testes
Voltando-
Criamos um projeto Aplicativo Console
Alura.LeilaoOnline.ConsoleApp

criamos uma referencia ao projeto --> adicionando


o projeto lá nas referencias
e alem disso tem que importar
using Alura.LeilaoOnline.Core

+++++++++++++++++++++++++++++++++++++
Problemas ao referenciar uma classlibrary do .net framework core - C#
link: Muito Importante
https://pt.stackoverflow.com/questions/268091/problemas-ao-referenciar-uma-
classlibrary-do-net-framework-core-c

--------------------------------------------------------------------
Não faz. Os dois frameworks são coisas diferentes e incompatíveis. |
|
Pra isto existe o .NET Standard, você pode fazer com que a class |
library tenha como target o .NET Standard e isso vai fazer com |
que ela possa ser usada tanto em projetos |
.NET Core como em projetos .NET Framework. |
-------------------------------------------------------------------

var leilao = new Leilao("Van Gogh");


var fulano = new Interessada("Fulano",leilao);
var maria = new Interessada("Maria", leilao);

leilao.RecebeLance(fulano, 800);
leilao.RecebeLance(maria, 900);
leilao.RecebeLance(fulano, 1000);

Console.WriteLine(leilao.Ganhador.Valor);

leilao.TerminaPregao();
Console.WriteLine(leilao.Ganhador.Valor);

//depois ele troca o projeto na inicializaçao para o console


//Aí tinha que dar isso mesmo 1000 reais o lance
ganhador do fulano
Agora temos um códigozinho que verificamos se aquele código que escrevemos
funcionalidade está funcionando
++++++++++
Só que a gente pode pensar em outras situações

leilao.RecebeLance(fulano, 800);
leilao.RecebeLance(maria, 900);
leilao.RecebeLance(fulano, 1000);
leilao.RecebeLance(maria, 990);
//vamos ter 990 escrito no terminal do console , e está errado
Então sabemos que nosso código não está legal
//Entao aquele código que pega o ultimo lance
//nao está funcionando
E isso é bom, tivemos um retorno rápido do nosso erro
problema e as pessoas nao utilizaram em produçao
graças a Deus

A gente nesse contexto fizemos um processo de Teste


O que é teste no final das contas?Dentro do contexto de desenvolvimento
de software?R:É fazer uma avaliação,verificação. Checar, tentar usar aquilo
Isso é o contexto de teste.Dentro do contexto de teste de software.É voce ter um
processo
que acontece para verificar se aquele software está atendendo os requisitos
funcionais,não funcionais tudo mais.O que nos fizemos aqui foi um teste

+++++++++
Para dar um pause no final da execuçao do console
podemos usar Console.Read() ou executar com
CONTROL+F5

Então agora substituimos nosso trabalho manual


pelo que a máquina faz para mim
Então podemos executar isso várias vezes de maneira rápida
de uma maneira inclusive de eu ficar pensando muito
Entao aqui nos temos um teste automatizado
OBS[TESTE AUTOMATIZADO NAO ESTÁ COMPLETO]
NO PRÓXIMO VIDEO ELE DIZ O PORQUE ELE NAO ESTÁ COMPLETO

------------------------------
Objetivos da aula
------------------------------

Como garantir que meu sistema está pronto?


Como garantir que meu sistema não tem problemas ou defeitos?
Essa discussão vai nos fazer conhecer a necessidade
de um conjunto de testes abrangente e automatizado.
Para atender essa necessidade, vamos aprender como
escrever testes usando o C# com xUnit dentro do Visual Studio.

------------------------------
Estrutura de teste automatizado
------------------------------
Esse é um link que mostra um pouco dessa incompletude
esse link é uma proposta de padrão para vc organizar,arrajar,
formatar o código que são métodos em testes unitários
e
http://wiki.c2.com/?ArrangeActAssert

Para você organizar esses códigos que sao testes automatizados,


voce tem que organizar em 3 sessões funcionais
1-Arranjar todas as precondiçoes,condiçoes de entrada
(digamos que é o cenário que você vai arrumar) chamado
ARRANGE
2-DEIXAR BEM CLARO O MÉTODO QUE ESTÁ SENDO TESTADo
nós chamais de ACT açao
3-É onde você vai verificar dos resultados que sao esperados,
que vc espera que ocorra depois de executar o metodo sob teste

é o Triplo AAA

++++++++++++++++++++++++++++++++++++++++++
Asset com [Console].WriteLine não é automatizado
Por isso o teste não está completo

Console.WriteLine(leilao.Ganhador.Valor);

//--aqui estaria automatizado


var valorEsperado = 1000;
var valorObtido = leilao.Ganhador.Valor;

if (valorEsperado == valorObtido)
{
Console.WriteLine("Teste ok");
}
else
{
Console.WriteLine("Teste FALHOU");
}

++++++++++++++++++++++++++++++
//Aqui nenhum de nos precisa saber a resposta
pode ser qualquer pessoa a executar o teste

static void Main()


{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");
var fulano = new Interessada("Fulano",leilao);
var maria = new Interessada("Maria", leilao);

leilao.RecebeLance(fulano, 800);
leilao.RecebeLance(maria, 900);
leilao.RecebeLance(fulano, 1000);
leilao.RecebeLance(maria, 990);

//Act - método sob teste


leilao.TerminaPregao();

//Assert
Console.WriteLine(leilao.Ganhador.Valor);

//---------------------------------ou
//--aqui estaria automatizado
var valorEsperado = 1000;
var valorObtido = leilao.Ganhador.Valor;

if (valorEsperado == valorObtido)
{
Console.WriteLine("Teste ok");
}
else
{
Console.WriteLine("Teste FALHOU");
}
//Console.Read();

OUTRA LITERATURA, MANEIRA DE REPRESENTAR O TESTE


https://martinfowler.com/bliki/GivenWhenThen.html
que é com GivenWhenThen
que é uma tecnica utilizado por
SpecificaçaoByExample
given-cenario
when-quando vc está atuando em cima do que voce quer testar
the -é verificacao das espectativas

-TER RETORNO MUITO RÁPIDO É A VNTAGEM DE TER


TESTES AUTOMATIZADOS

++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
UNIT TEST-é a parte mais interna de que você
pode testar. Em geral isso é representado por um método
em uma classe.Mas nem todos os metodos de uma classe terão
de ser testados unitariamente. VOce pode testar um método
que chama outros métodos internamente.

É quando você está testando uma unidade de trabalho em específica

Depois nos pegamos o teste e tiramos do main para


ser um de vários testes que serao feitos no main

A verificaçao está sendo muito repetida


e podemos extrair ela

Depois mudamos a cor se tiver passado o teste para green


a fonte e vermelho se nao tiver passado

class Program
{
private static void Verifica(double esperado,double obtido)
{
var cor = Console.ForegroundColor;
if (esperado == obtido)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Teste ok");
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(
$"Teste FALHOU! Esperado: {esperado} , obtido: {obtido}");
}
Console.ForegroundColor = cor;

+++++++++++++=
mas esse trabalho já foi feito para gente nao precisamos ficar preocupando com isso
e vamos aprender a usar no próximo video
COMeçamos a afastar do negócio e isso nao é legal
------------------------------
A biblioteca XUnit
------------------------------

Continue o seu trabalho que é implementar o código de negócios


regra de negocios

AGORA VAMOS USAR AS FERRAMENTAS QUE NOS AJUDAM A IMPLEMENTAR OS TESTES


QUE SAO CHAMADOS DE FRAMEWORKS DE TESTES

OS MAIORES CONCORRENTES DE FRAMEWORKS NA PLATAFORMA .NET SAO


-xUNIT
-MSTEST
-NUNIT
(UTILIZADOS COMO FRAMEWORKS DE TESTS)

NESSE CURSO VAMOS USAR O xUNIT


- PORQUE ?[TEM ARTIGO PARA LER]
nele Chris explica o porque escolheou o xUNIT e não
os outros 2
[microsoft está fazendo seus testes com xUNIT]

Os conceitos que aprendemos em um , são aplicaveis nos outros


[TEM um link que compara os atributos, conversoes]

Vamos adicionar um novo projeto de teste e esse


projeto vai ser do xUNIT
Alura.LeilaoOnline.Tests
[ele depende de alguns pacotes do NUGET]
ele apaga o arquivo que vem como default UnitTest1.cs
e cria nova classe chama LeilaoTestes.

++++++++++++++++++++++++
++++++++++++++++++++++++
O XUNIT NÃO TRABALHA COM MÉTODOS ESTATICOS

TROCA
private static void Verifica(double esperado,double obtido)
POR
Assert.Equal(valorObtido, valorEsperado);
using Xunit;

AGORA ELE NAO VAI ME MOSTRAR MAIS OS TESTE


ELE VAI MOSTRAR UMA JANELINHA QUE ESTÁ INTEGRADA AO VISUAL STUDIO
AGORA NO VS TEMOS UMA ABA CHAMADA TESTE>EXECUTAR>TODOS TESTES
TEM OUTRA OPCÓES

E SE EXECUTAR DESSE FORMA O XUNIT NAO VAI IDENTIFICAR OS


MÉTODOS COMO TESTES MESMO TENDO 2
PARA ISSO TEMOS DE INFORMAR
que os métodos sao testes
++++++++++++++++++++++++++
public class LeilaoTestes{
[Fact]
public void LeilaoComVaiosLances()

[Fact]
public void LeilaoComApenasUmLance()
}

++++++++
Tem outra forma de visualizar e é bem melhor
-Teste->Janelas->Gerenciador de testes
TEMOS RESULTADO DE FORMA VISUAL
VERDE VERMELHO

SE DER ERRO TEM COMO VER MAIORES INFORMAÇOES


ATÉ PILHA DE EXECUCAÓ

------------------------------
ENCONTRE O ERRO
------------------------------

//para rodar os testes


Anotar cada método de teste com [Fact]
Tornar a classe de testes pública
Importar o namespace do xUnit

------------------------------
REFERÊNCIAS UTILIZADAS
------------------------------

VÁRIAS REFERENCIAS AQUI

------------------------------
o que aprendemos?
------------------------------

conheceu o padrão Arrange, Act e Assert


usou testes automatizados para agilizar o feedback do seu código
conheceu o framework xUnit, com facilidades para verificar suas expectativas e
integração com o Visual Studio
criou métodos de teste do xUnit através da anotação [Fact]

---------------------------------------------------------
02.Organizando seus testes
---------------------------------------------------------

------------------------------
Escrevendo mais testes
------------------------------

++++++++++++++++++++++++
VOCÊ PODE TER MAIS DE UM ASSERT NA VERIFICAÇÃO
No caso está relacionado ao ganhador e faz sentido verificar mais
de uma propriedade tanto o valor quanto o cliente que foi
o ganhador
E o método Equal tem sobrecarga para tipos diferentes
e tem para o Equal para qualquer tipo, que no caso foi usada
<T>
Assert.Equal(valorObtido, valorEsperado);
Assert.Equal(beltrano, leilao.Ganhador.Cliente); //o segundo <T>

QUANDO EU SEI QUE TERMINEI DE FAZER OS TESTES PARA ESSA FUNCIONALIDADE?


QUAL É O MINIMO DE TESTES QUE PRECISO FAZER PARA GARANTIR
O MAXIMO DE SEGURANÇA E CONFIABILIDADE POSSÍVEIS?

OUTRO PONTO, A MEDIDA QUE OS TESTES CRESCEM, CODIGOS CRESCEM


VAI SE REPETIR CÓDIGO, ENTÃO COMO FAZEMOS
PARA ORGANIZAR NOSSO CÓDIGO?

------------------------------
Escrevendo mais testes
------------------------------

Quantos testes são o bastante?

Será que estou criando os testes certos? Afinal, que cenários devo testar?

Como organizo meus testes? Que nome devo dar às classes e métodos de testes?

Durante essa reflexão vamos conhecer


uma missão importante do testador e como o
xUnit pode nos ajudar a cumprí-la. Além disso
iremos organizar nossos testes segundo um padrão específico.

------------------------------
O que devo testar
------------------------------

Como saber que terminei os testes?


Como saber se a minha funcionalidade está confiável, pronta para
subir para produção?
R:Procurar alguém que tenha mais esperiencia e ele funcionar
como mentor na sua jornada de testador.Cara que tenha experiência que já
tenha participado de QA,já tenha feito outros testes e tudo mais.Ela
vai ter mais input para dar para você.
Vamos tentar usar o padraão ARRANGE ACT ASSERT ou
o GIVEN WHEN THEN
1-cenário de entrada, condiçoes de entrada
2-o que está sendo testado
3-Verifica as saida em relacao a entrada que foi testada'

ELE ESCREVEU A DESCRIÇAO DAS ETAPAS


E DEPOIS REMOVEU PASSANDO PARA O TRELLO

{print}[given when then] descricao dos testes


ELE MOSTRA QUE NOS CASOS , QUE A EXPECTATIVA NAO MUDA,MESMO
QUE O VALOR DE ENTRADA SEJAM DIFERENTES
ENTAO ELE PODIA TRANSFORMAR AS QUATRO DESCRIÇOES EM UMA
SÓ POIS NO CASO ELE NOS TESTES ESTÁ USANDO
++++++++++++++++++++++
TRABALHANDO MUITO COM UMA TÉCNICA TESTE CHAMADA DE
CLASSE DE EQUIVALÊNCIA - EQUIVALENCE PARTIONING
Que é basicamente particionar o dado de entrada em
várias partiçoes para que voce seja mais eficiente na hora de
criar seus testes

Aí ele disse que foi bastante ineficiente porque ele criou quatro testes
que estão testando a mesma partiçao de entrada
afinal nao importa se tem 10 clientes, 10 lances,2lances 1lance
POIS A EXPECTATIVA É SEMPRE A MESMA
O VALOR EXPERADO É O MAIOR VALOR DADO. eNTÃO A GENTE PODE
REPRESENTAR TADO AQUI EM APENSA UM CENÁRIO

AÍ DA MESMA FORMA ELE VAI APAGAR AQUILO E


MAS NO CÓDIGO ELE VAI USAR UM RECURSO QUE O XUNIT
VAI UTILIZAR

++++++++++++++++++++++
+++++++++++++++++++++
eNTAO SUA MISSAO COMO TESTADOR É ACHAR A PARTIÁO, CLASSES DE
EQUIVALENCIA, E NÃO EXISTE UMA FORMULA PARA ISSO.
VOCE VAI TER A SUA EXPERIENCIA E SUA MENTORIA QUE VAI TI AJUDAR
-TEM OUTRA ANALISE TBM DE FAZER ANALISE DE FATORES
DE FRONTEIRA
PENSAR NAS FRONTEIRAS DOS TIPOS DE DADOS
EX:NESSE CASO TEMOS O DOUBLE
(VALOR NEGATIVO)
(CLIENTE QUE NAO TENHA SIDO CRIADO-VALOR NULL)
COMO VAI SE COMPORTAR

++++++++++++
CENARIO-> LEILAO SEM NENHUM LANCE
O QUE PRECISA ACONTECER QUANDO LEILAO TERMINAR SEM LANCE NENHUM?

------------------------------
Leilão sem lances
------------------------------

Quem vai ser o ganhador de um leilao que nao tiver nenhum lance?
E você nao tem que decidir você mesmo arbitrariamente.
É claro que as vezes estamos pressionado por prazo do projeto
por tudo mais.Querendo que vc termina e a gente acaba tomando decisoes
arbitrarias

Essa é uma decisão que ddeve ser tomada por alguem q é dona
do produto, por quem é dona do Bancklog(PO)
Pessoa que sabe do negócio
Ai vamos considerer que ele falou que quando n tiver ganhador
vai ter ganhador é o valor 0

entao estamos com


Cenários
Cenário 1
Dado leilão pelo menos um lance
Quando o pregão/leilão termina
Então o valor 'e o maior valor dado
e o cliente ganhaddor é que deu o maior lance

Cenário 2[fazer esse agora]


Dado leilão sem qualquer lance
Quando o pregão/leilão termina
Então o valor do lance ganhador é zero
var valorEsperado = 0;
var valorObtido = leilao.Ganhador.Valor;
Assert.Equal(valorEsperado, valorObtido);

testamos e dar erro , pois nao tem elementos


Justamente quando chamamos o método Last

aí para fazer o teste passar

Ganhador = Lances
.OrderBy(l => l.Valor)
.LastOrDefault();

//para

Ganhador = Lances
.DefaultIfEmpty(new Lance(null,0)) //vai retornar este obj quando estiver vazio
.OrderBy(l => l.Valor)
.LastOrDefault();

+++++++++++++=
++++++++++++++
Vale a pena estudar a API do .NET
para ser mais rápido na hora de criar testes
olha o exemplo acima

NO TRELLO TEMOS 2 CENÁRIOS MAS NO CÓDIGO TEMOS 5 TESTES ,


COMO FAZEMOS PARA REDUZIR ISSO

------------------------------
Teorizando com xUnit
------------------------------

Temos de ser eficiente criando um teste para cada classe de equivalencia


Mas para nosso Leilao com pelo menos um Lance temos
4 testes , e nessa questão vamos ter código duplicado
[EVITAR CÓDIGO DUPLICADO]
Reduzindo o seu código torna ele mais fácil de manter e a mesma
coisa acontece para códigos de testes

Então, será que o xUnit ajuda a reduzir nosso código para uma
classe de equivalência, sim
O XUNIT TEM UM RECURSO CHAMADO DE [TEORIA]
ONDE VOCÊ PODE FAZER UMA BRINCADEIRA COM TESTES QUE NÓS TEMOS

Aí no caso o cenário/metodo de teste LeilaoSemLance vai ficar da forma


que está aí, pq é o unico método que tenho para classe de equivalencia
do leilão sem lances

+++
Mas no outro tem 4 testes que queremos reduzir para um só
para isso
trocamos o atributo [Fact] para o [Theory]
e essa notaçao vai transformar esse método a partir de algumas
coisas que temos q fazer
Quando fazemos isso vamos ter um erro de compilacao
- o motivo é que temos de passar vários dados de test,
por exemplo lances ordenados, lances desordenados,lances com
mais de um cliente, leilao com apenas um lance
[Theory]
public void LeilaoComVariosLances()

??Como fazer para enviar dados de testes para o método


comattributo [Theory]??

[Theory]
[InlineData(new double[] {800, 900, 1000, 1200})]
[InlineData(new double[] { 800, 900, 1000, 990 })]
[InlineData(new double[] { 800 })]
public void LeilaoComVariosLances(double[] ofertas )

///por essa notçao passamos os dados de entrada


///é os valores que queremos dar de lance
//para agrupar esses valores, nos temos de colocar em um dado
//de entrada só e aqui nos fizemos por ARRAY, mas pode ser outros
//tipos de coleçao
///+++esses dados de entrada tem que ser recebidos como dados de entrada
//desse método leilaocomvarioslances como argumento

+++MESMO CÓDIGO RECEBENDO 3 CONJUNTOS DE DADOS DIERENTES

++++
SE EU QUISER PASSAR DADOS DE ENTRADA USAMOS A NOTAÇAO
[THEORY] ,SE EU NAO IMPORTAR OS DADOS DE ENTRADA QUE VAI PASSAR
A EXPECTATIVA VAI SER SEMPRE A MESMA, NOS USAMOS A NOTAÇAO
[FACT]

FACTS SÃO SEMPRE VERDADEIROS. ELES TESTAM CONDIÇÕES INVARIANTES


THEORIES SAO TESTES SAO OS QUAIS SAO SOMENTE VERDADE PARA UM
CONJUNTO PARTICULAR DE CONJUNTO DE DADOS

A VERSAO 4 VEM COM SUPORTE PARA DATA-DRIVEN TESTS CHAMADO THEORIES


THEORY É ORIENTADO POR DADOS

[Theory]
[InlineData(1200, new double[] {800, 900, 1000, 1200})]
[InlineData(1000, new double[] { 800, 900, 1000, 990 })]
[InlineData(800, new double[] { 800 })]
public void LeilaoComVariosLances(double valorEsperado,double[] ofertas )
{

foreach(var valor in ofertas)


{
leilao.RecebeLance(fulano, valor);
}

Assert.Equal(valorObtido, valorEsperado);
aí é meio que considerado como um teste apenas

EXEMPLO

[Theory]
[InlineData(7, 2, 5)
public void RetornaSomaDeDoisNumeros(int resultadoEsperado, int num1, int num2)
{
//Act
var resultadoObtido = num1 + num2;
//Assert
Assert.Equal(resultadoEsperado, resultadoObtido);
}

------------------------------
Nomenclatura
------------------------------

Nome que temos de dar para os nossos testes?

Diretrizes da Microsoft

Naming your tests


The name of your test should consist of three parts:

The name of the method being tested.


The scenario under which it's being tested.
The expected behavior when the scenario is invoked.

Nome da classe de teste será a nome da c;asse


o nome de teste sendo testado
para nosso exemplo LeilaoTerminaPregao

e os metodos de teste vao ter as duas partes


-comportamento esperado
-cenário sendo testado

LeilaoTest->LeilaoTerminaPregao (nome da classe)


LeilaoComVariosLances
->RetornaMaiorValorDadoLeilaoComPeloMenosUmLance(double valorEsperado,double[]
ofertas )
(nome método)
LeilaoSemLances()
->RetornaZeroDadoLeilaoSemLances(metodo)

DESSA FORMA JÁ É UMA DOCUMENTAÇAO VIVA

++ELE PERCEBE QUE TEM MAIS UMCENÁRIO A SER TESTADO

CENARIO3
DADO LEILÃO FINALIZADO COM X LANCES
QUANDO LEILAO RECEBE NOVA OFERTA DE LANCE
eNTÃO A QTD DE LANCES CONTINUA SENDO X
+++
ESTE CENÁRIO NUMERO 3 É UMA NOVA CLASSE DE EQUIVALENCIA?????
r:é NÃO
ATÉ PQ NAO ESTA TESTANDO O MESMO MÉTODO,POIS NAO ESTA TESTANDO MAIS
O TERMINA PREGAO
VOU TESTAR O OFERTADELEILAO
É UMA NOVA CLASSE DE EUQIVALENCIA PARA O NOVO METODO
MAS NAO DO ANTIGO

public class LeilaoRecebeOferta


{
[Fact]
public void NaoPermiteNovosLancesDadoLeilaoFinalizado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");
var fulano = new Interessada("Fulano", leilao);
leilao.RecebeLance(fulano, 800);
leilao.RecebeLance(fulano, 900);
leilao.TerminaPregao();//agora faz parte do cenário

//Act - método sob teste


leilao.RecebeLance(fulano, 1000);

//Assert
var valorEsperado = 2;
var valorObtido = leilao.Lances.Count();

Assert.Equal(valorEsperado, valorObtido);
}
}

//modificando de [Fact] para [Theory]

------------------------------
O que aprendemos?
------------------------------

conheceu as classes de equivalência e descobriu que é missão do testador descobrí-


las
aprendeu sobre as anotações do xUnit [Theory] e [InlineData], que são usadas para
injetar cenários diferentes no mesmo teste
descobriu um padrão para nomear seus métodos e classes de teste

---------------------------------------------------------
03.Não deixe o sistema regredir
---------------------------------------------------------

------------------------------
Manutenção dos testes
------------------------------

Ele introduziu uma nova funcionalidade


E no momento que ele introduziu uma nova funcionalidade quebrou
o código que estava funcionando, com isso os testes tbm
+++O SISTEMA AO INVES DE EVOLUIR ELE REGREDIU

E ESSES TESTES COSTUMAM SER CHAMADOS DE TESTES DE REGRESSÃO


:QUE EVITAM A REGRESSAO DO SISTEMA

COMO EU FAÇO PARA CORRIGIR E DEIXAR OS TESTES NOVAMENTE PASSANDO?


SENDO APROVADOS NO VISUAL STUDIO
R:TEM QUE FAZER UMA MUDANÇA NOS TESTES, ISSSO ACONTECE
AS VEZES TEMOS DE FAZER MANUTENÇAO NOS PROPRIOS CENARIOS
QUE CRIEI

ele teve de adicionar


leilao.IniciaPregao(); antes dos lances
para voltar funcionar

+++++++++++++
MUITAS VEZES NOS MUDAMOS O COMPARTAMENTO E ALGUNS TESTES DEIXAM DE PASSAR
MUITAS VEZES ALGUNS TEM QUE SER REMOVIDOS DA SUA SWITCH DE TESTE,
POIS ELES NÃO FAZEM MAIS SENTIDO
ALGUNS TEM QUE SER MODIFICADOS, MANTIDOS
+++++++++++++++++++
DAÍ A IMPORTANCIA DE VOCÊ TER CÓDIGO DE QUALIDADE EM SEUS TESTES

+++
COMO EU GARANTO A DISCIPLINA DE SEMPRE TER TESTES PARA FUNCIONALIDADES
QUE CRIE?

Como evitar que a implementação de novas


funcionalidades quebre o sistema?
Para responder essa pergunta vamos conhecer uma
prática que vai permitir a evolução do nosso
conjunto de testes a cada funcionalidade.
Esse conjunto de testes servirá como testes
de regressão para a próxima funcionalidade e
espera-se que aumente a confiança no código
que vai subir para produção.

------------------------------
Novos testes a cada funcionalidade
------------------------------
+++++++++++++++++++++
Teste para cada nova funcionalidade
-ratica de ter um testador , equipe de teste, uma equipe de QA
Essa equipe fica posicionada justamente para testar os incrementos do
software que você faz que o desenvolvedor cria. Eles pegam incrementos
de software e realizam testes a partir disso aí.
Então é uma prática comum e deia o desenvolvedor confortável
em até não fazer testes.Pq ele sabe que alguém vai pegar
esses problemas que ele pode ter injetado.Pode
ter feito o sistema regredir.
Testes automaticos que estam rodando em nossa máquina dão um
feedback basicamente imediato. De que se o nosso sistema regrediu ou não
Isso faz que meu foco continue sendo ainda, naquela funcionalidade

Atuar apenas em uma coluna como desenvolvendo.


A equipe de testes que vai testar.se a equipe de testes pegar um erro
vc(desenvolvedor) vai ter que para o que está fazendo e mudar de foco.
Mudar seu contexto para recuperar tuo aquilo que vc fez

Como eu crio a disciplina de testes automatizados?


Além da equipe de testes. Eu como desenvolvedor, desenvolvo testes
sempre a cada nova funcionalidade

+++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++
AO INVÉS DE DESENVOLVER E DEPOIS TESTAR
PRIMEIRO A GENTE CRIA OS TESTES E DEPOIS DESENVOLVE
FAMOSO TDD
PRIMEIRO PENSAMOS EM NO MINIMO UM CENÁRIO E CRIAMOS
O TESTE E ESSE TESTE VAI FALHAR PORQUE VOCÊ NÃO ESCREVEU
CÓDIGO AINDA. AÍ SIM A GENTE VAI FAZER OS TESTES FUNCIONAIS
ESCREVENDO A FUNCIONALIDADE
VAMOS TENTAR FAZER ISSO EM UMA PRÓXIMA FUNCIONALIDADE

++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++
PRATICA CONTRA INTUITIVA, EM QUE PRIMEIRO VOCE CRIA OS TESTES E DEPOIS
AS PRATICAS DE NEGÓCIO.
ESSA PRÁTICA É MUITO ITILIZADA NOS TIMES ÁGEIS
E É CHAMA DE TESTE DRIVEN DEVELOPMENT - TDD
PORQUE É O DESENVOLVIMENTO QUE ESTÁ DIRIGIDO PELOS
TESTES
DESENVOLVIMENTO ORIENTADO PELOS TESTES
DESENVOLVIMENTO QUE SERÁ ORIENTADO PELOS TESTES QUE ESTÃO FALHANDO

------------------------------
Praticando TDD
------------------------------

Ele vai criar um novo teste


para nova funcionalidade:CLIENTES NÃO PODE PROPOR LANCES SEGUIDOS
Dadoleilao iniciado E interessado X realizou o ultimo lance
Quando mesmo interessado X realiza o próximo lance
Então leilão não aceita o segundo lance

O método sob teste é o Recebe Oferta por isso vmos


escreveer na classe leilaoRecebeOferta

foi escrito o teste

[Fact]
public void NaoAceitaProximoLanceDadoMesmoClienteRealizouUltimoLance()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");
var fulano = new Interessada("Fulano", leilao);
leilao.IniciaPregao();
leilao.RecebeLance(fulano, 800);

//Act - metodo sob teste


leilao.RecebeLance(fulano, 1000);

//Assert
var qtdeEsperada = 1;
var qtdeObtida = leilao.Lances.Count();
Assert.Equal(qtdeEsperada, qtdeObtida);
}

E VAI FALHAR
entao vamos escrever o codigo de produção

++++
MAS NÃO ADIANTA EXECUTAR APENAS O TESTE NOVO,
TEM QUE EXECUTAR TODA SWITCH DE TESTES

++++++++
AÍ NOVAMENTES OS TESTES VOLTARAM A FALHAR , E ISSO PORQUE O MEU CENÁRIO
MUDOU

AÍ PARA CONSERTAR ISSO VC PODE MUDAR A EXPECTATIVA(OU SEJA


DADOS DE ENTRADA) OU PODEMOS MUDAR O CENÁRIO
aí ele colocou para fazer lances alternado entre a maria e o
fulano
ASSIM TODOS VOLTARAM A FUNCIONAR

++++++++++++++++++++++++++++=
O TDD
NÓS DÁ A DISCIPLINA DE SEMPRE PENSAR NOS TESTES PRIMEIRO

------------------------------
Melhorando nosso código
------------------------------

Ele nao achou muito bom a soluçao


for (int i = 0; i < ofertas.Length; i++)
{
var valor = ofertas[i];
if ((i % 2) == 0)
{
leilao.RecebeLance(fulano, valor);
}
else
{
leilao.RecebeLance(maria, valor);
}
}

entao ele vai criar um método boleano se o lance é aceito ou nao

ele fez melhoria, criando metodo privado para melhorar criterioos de


aprovaçao
private bool NovoLanceEhAceito

private bool NovoLanceEhAceito(Interessada cliente,double valor)


{
return (Estado == EstadoLeilao.LeilaoEmAndamento)
&& (cliente != _ultimoCliente);
}

public void RecebeLance(Interessada cliente, double valor)


{
if (NovoLanceEhAceito(cliente, valor))
{
_lances.Add(new Lance(cliente, valor));
_ultimoCliente = cliente;
}

E AGORA, COMO FAZEMOS PARA TESTAR MÉTODOS PRIVADOS UMA VEZ QUE
ELES NÃO SAO VISIVEIS NA CLASSE DE TESTE???????
POR UM LINK DA MICROSOFT ELE DIZ QUE NA MAIORIA DAS VEZES
VOCE NAO VAI TER NECESSIDADE DE TESTAR UM MÉTODO PRIVADO
E DIZEM QUE EM ALGUM MOMENTO AQUELE MÉTODO PRIVADO VAI SER
SENSIBILIZADO POR UM MÉTODO PÚBLICO
E O MÉTODO PUBLICO VAI ESTAR SENSIBILIZANDO O METODO PRIVADO
+++++++++++++++++++++++++++++++
ENTAO ELE FEZ UMA MELHORIA NO NOSSO CÓDIGO SEM MUDAR ELE EXTERNAMENTE
E QUANDO A PESSOA FAZ ISSO DIZEMOS QUE ELE FEZ UMA REFATORAÇAO
MUDAR O SISTEMA INTERNAMENTE SEM MUDAR O COMPORTAMENTO EXTERNO
SENDO ISSO NOS ENCERRAMOS O CICLO DO TDD

------------------------------
O que aprendemos?
------------------------------

Nessa aula você:

-aprendeu o que são testes de regressão


-percebeu que testes também precisam ser
mantidos e até mesmo descartados
-conheceu a prática TDD, Test Driven Development,
e a aplicou em uma nova funcionalidade
-descobriu que o TDD permite que seu código seja
melhorado sem regredir o sistema, termo conhecido como refatoração
-conheceu o ciclo TDD: escrever testes que falhem
>> corrigir os testes ajustando código de produção >> refatorar o código

---------------------------------------------------------
04.Testando todos os comportamentos
---------------------------------------------------------

------------------------------
Terminando leilão sem pregão
------------------------------

Vimos que nosso termina o pregao sem sequer ter iniado


e perguntamos para nosso cliente
E ele diz que isso nao pode acontecer

aí criaremos
[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()

++++++++
Agora queremos testar se uma exceçao foi lançada

[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");

try
{
//Act - método sob teste
leilao.TerminaPregao();
}
catch(System.Exception e)
{
//Assert
Assert.IsType<System.InvalidOperationException>(e);
}
}

++++MAS DESSE JEITO VAI PASSAR O TESTE PQ ELE NAO PEGA A EXCEÇAO
O leilao.TerminaPregao();NAO LANCA EXCEÇAO
PARA ISSO PRECISAMOS FAZER UMA GAMBIARRA

[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");

try
{
//Act - método sob teste
leilao.TerminaPregao();
Assert.True(false);
}
catch(System.Exception e)
{
//Assert
Assert.IsType<System.InvalidOperationException>(e);
}
}

AGORA REALMENTE ELE FALHA


TOP
POIS COM Assert.True(false); GERAMOS UMA FALHA

AGORA PODEMOS COMEÇAR A IMPLEMENTAR A FUNCIONALIDADE

MAS SERÁ QUE TEM UMA FORMA MAIS INTERESSANTE DE TESTAR EXCEÇOES COM
XUNIT??

------------------------------
Exceções com xUnit
------------------------------

VAMOS MODIFICAR O MÉTODO

[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");

try
{
//Act - método sob teste
leilao.TerminaPregao();
Assert.True(false);
}
catch(System.Exception e)
{
//Assert
Assert.IsType<System.InvalidOperationException>(e);
}
}

PARA ->

[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");

//Assert
Assert.Throws<System.InvalidOperationException>(
//Act método sob teste
() =>leilao.TerminaPregao()//passar como delegate
);
}

//uso com xUNIT

Um dos motivos de ser escolhido o xUNIT em detrimento aos outros 2


é a forma de testar exceçao, é mais elegante

aí modificamos

public void TerminaPregao()


{
if (Estado != EstadoLeilao.LeilaoEmAndamento)
{
throw new System.InvalidOperationException();
}
Ganhador = Lances
.DefaultIfEmpty(new Lance(null,0))
.OrderBy(l => l.Valor)
.LastOrDefault();
Estado = EstadoLeilao.LeilaoFinalizado;
}

//colocando a exceçao

e regrediu os testes por conta de que criamos os cenários sem


iniciar o leilao antes do termino

Adicionamos mais um comportamento ao leilao sem ter iniciado


+++++++++++++++++++++++++=
É POSSÍVEL VERIFICAR A MENSAGEM DA EXCEÇAO TBM

[Fact]
public void LancaInvalidOperationExceptionDadoPregaonaoIniciado()
{
//Arranje-Cenário
var leilao = new Leilao("Van Gogh");

//Assert
var excecaoObtida = Assert.Throws<System.InvalidOperationException>(
//Act método sob teste
() =>leilao.TerminaPregao()//passar como delegate
);
//--------
var msgEsperada = "Não é possível terminar o pregão tenha começado.
Para isso, utilize o método IniciaPregão";
Assert.Equal(msgEsperada, excecaoObtida.Message);
}

//para iso colocamos a mensagem na exceçao lancada

public void TerminaPregao()


{
if (Estado != EstadoLeilao.LeilaoEmAndamento)
{
throw new System.InvalidOperationException("Não é possível terminar
o pregão tenha começado. Para isso, utilize o método IniciaPregão");
}
Ganhador = Lances
.DefaultIfEmpty(new Lance(null,0))
.OrderBy(l => l.Valor)
.LastOrDefault();
Estado = EstadoLeilao.LeilaoFinalizado;
}

------------------------------
Testando outra exceção
------------------------------

namespace Alura.LeilaoOnline.Tests
{
public class LanceCtor
{
[Fact]
public void LancaArgumentExceptionDadoValorNegativo()
{
//Arranje
var valorNegativo = -100;

//Assert
Assert.Throws<System.ArgumentException>(
//Act
() => new Lance(null, valorNegativo)
);
}
}
}
------------------------------

public Lance(Interessada cliente, double valor)


{
if (valor < 0)
{
throw new System.ArgumentException("Valor do lance deve ser igual
ou maior que zero");
}
Cliente = cliente;
Valor = valor;
}
}

------------------------------
Referências Utilizadas
------------------------------

Referências usadas na aula


Diferenças entre os frameworks ao testar exceções

https://xunit.github.io/docs/comparisons

Visual Studio tem uma ferramenta de cobertura de código,


mas infelizmente apenas nas suas versões pagas.

https://docs.microsoft.com/en-us/visualstudio/test/using-code-coverage-to-
determine-how-much-code-is-being-tested

Esse artigo do Martin Fowler debate o real propósito


da cobertura de código, que em sua opinião (na minha também!)
deveria ser para encontrar partes não testadas do seu sistema
ao invés de ser uma métrica utilizada em contratos e objetivos do time.

https://www.martinfowler.com/bliki/TestCoverage.html

------------------------------
O que aprendemos
------------------------------

Nessa aula você:

descobriu que exceções também são comportamentos do sistema e também devem ser
testadas
conheceu o método Assert.Throws<>() que permite verifica
r a expectativa de lançamento de determinada exceção

---------------------------------------------------------
05. Ajudando no design do código
---------------------------------------------------------

------------------------------
Outra forma de avaliar o leilão
------------------------------
[Theory]
[InlineData(1200,1250,new double[] { 800,1150,1400,1250})]
public void RetornaValorSuperiorMaisProximoDadoLeilaoNessaModalidade(
double valorDestino,
double valorEsperado,
double[] ofertas)
{
//Arranje
var leilao = new Leilao("Van Gogh");
var fulano = new Interessada("Fulano", leilao);
var maria = new Interessada("Maria", leilao);

for(int i = 0; i < ofertas.Length; i++)


{
if ((i % 2 == 0))
{
leilao.RecebeLance(fulano, ofertas[i]);
}
else
{
leilao.RecebeLance(maria, ofertas[i]);
}
}

//Act
leilao.TerminaPregao();

//Assert
Assert.Equal(valorEsperado, leilao.Ganhador.Valor);
}

------------------------------
Objetivos da aula
------------------------------

Repare que o valor de destino do leilão não foi


utilizado na criação do cenário apresentado.
Mas como vou saber qual é o lance ganhador
nessa nova modalidade sem comparar o
valor do lance com o de destino?

Essa dificuldade nos leva a refletir


que algumas novas implementações vão
exigir que alteremos a interface de uma classe,
ou seja, como ela interage com outras classes.
Você verá que nesse exemplo teremos que mudar
a classe Leilao para aceitar um valor de
destino para essa modalidade.

O processo de planejar a interface de uma


classe é chamado de Design OO. Nosso objetivo
nessa aula é mostrar que o TDD também pode ajudar o design!

------------------------------
Teste ajudam o design
------------------------------

Até agora não tinhamos necessidade de fazer uma alteraçao


na interface da classe leilao

Qual é a definição de interface de uma classe?


[n é o recurso interface e sim interface de uma classe]
A interface de um objeto define como voce vai interagir
com ele. COmo interagimos com um obj?Atraves de seus metodos,
das suas propriedades e através de seu construtor.

OU seja, até agora não precisamos mudar como que a gente, interagia com
leilao.
++++++++++
O processo em que vc planeja como um objeto vai interagir com outro
Isso é chamado de design

+++++++++++++++++
++++++++++++++++
OS TESTES ESTÃO AJUDANDO A VALIDAR O DESIGN DAS MINHAS CLASSES.
A INTERFACE

vamos modificar a interface para quando no construtuor tenha um


vaor destino maior que zero, que seja outra modalidade de leilao
ela é por oferta superior mais proxima

public double ValorDestino { get; }

public Leilao(string peca,double valorDestino=0)


{
Peca = peca;
_lances = new List<Lance>();
Estado = EstadoLeilao.LeilaoAntesDoPregao;
ValorDestino = valorDestino;
}

//começa como null a propriedade Ganhado e depois tem um valor


public void TerminaPregao()
{
if (Estado != EstadoLeilao.LeilaoEmAndamento)
{
throw new System.InvalidOperationException("Não é possível terminar
o pregão tenha começado. Para isso, utilize o método IniciaPregão");
}
if (ValorDestino > 0)
{
//modalidade oferta superior mais próximo
Ganhador = Lances
.DefaultIfEmpty(new Lance(null, 0))
.Where(l => l.Valor > ValorDestino)
.OrderBy(l => l.Valor)
.FirstOrDefault();
}
else
{
//modalidade maior valor
Ganhador = Lances
.DefaultIfEmpty(new Lance(null, 0))
.OrderBy(l => l.Valor)
.LastOrDefault();
Estado = EstadoLeilao.LeilaoFinalizado;
}
}
------------------------------
Estratégia de avaliação
------------------------------

Mudar código sem mudar comportamento,mudar interface


Isso se chama refatoração. A atividade de refatoraçao deve
ser feita depois de todos os testes estarem passando

------------------------------
REferencias Utilizadas
------------------------------
++++++++++++++++
Talk de Michael Feathers sobre como testes melhoram o design
[voltar]

Você também pode gostar