Você está na página 1de 40

Testes Automatizados

com Selenium
Parte I

A importância de testar softwares cresce cada vez mais. Alguns


softwares tendem a ser mais complexos e com muitas features.
Hoje, desenvolver sem testes, com toda certeza, fará com que sua
aplicação esteja pronta para um prato cheio de erros!

Automatizando
Imaginemos um formulário com 20 campos, obrigatórios,
validações e dentre outras surpresinhas? Isso acaba sendo
cansativo e demorado para preencher todos esses campos,
correto? Sim, demora muito.

Neste exemplo de cenário, podemos fazer com que esse


preenchimento seja de forma bem simples e intuitiva; sem dores
de cabeça, sem complexidade de forma “humanizada”,
automatizando todo esse processo.

Alguns benefícios da automatização


- Mais rapidez do que teste manual
- Reusabilidade de código
- Redução de custos
- Poupa-se mais tempo

Dentre outras coisinhas a mais… :o)


Selenium
Neste post, venho demonstrar o uso do Selenium, que é um
framework que nos permite automatizar as ações de um usuário
em um navegador, dessa forma conseguimos automatizar tarefas
desgastantes que necessitem ser feitas no navegador. Funciona em
um grande número de navegadores, também permite escrever
testes em diversas linguagens de programação (de Java a Erlang,
passando por C# e PHP). Mais informações aqui.

Como utilizar o Selenium com C#?


Simples! Precisaremos de algumas coisinhas:

 Visual Studio instalado


 Um browser de sua preferência (eu uso o Chrome)
 Um webdriver do seu browser, qual fará comunicação com a
api do Selenium. (No caso do Chrome, pode ser feito
download aqui)
 E uma meia dúzia de código :o)

Cenário
Faremos um exemplo básico de abrir a página do Bing, consultar
alguma coisa e fazer uma validação se o o total do resultado foi o
esperado.

Mãos à massa!
Primeiro teremos que copiar o nosso WebDriver (já feito
download) para a pasta do nosso projeto ou em qualquer outro
lugar. Escolhi deixá-lo na pasta do Google Chrome.
C:\Program Files (x86)\Google\Chrome

Vamos criar um projeto de testes no Visual Studio


chamado BingSelenium e logo em seguida, instalar via nuget o
pacote do Selenium:

install-package Selenium.WebDriver

Antes de tudo, vamos a uma pequena explicação:

1- Webdriver: uma api de comunicação com Selenium Framework,


que usa extensões ou recursos nativos oferecidos pelo próprio
navegador para controlá-lo diretamente.
2- FindElement encontra um único elemento. FindElements
localiza vários elementos.
3- By é uma classe estática com alguns métodos para localizar
elemento(s).
4- Métodos que retornam o objeto que estamos localizando pela
sua propriedade, id, nome etc…
FindElement retorna um WebElement e o FindElements uma
lista de WebElement (List<WebElement>)

Agora que entendemos um pouco, iremos mapear os nossos


objetos da tela, antes de fazer uma chamada ao WebDriver:
Textbox de pesquisa e um botão de ação

Vamos inspecionar a tela do Bing e verificar os IDs desses


elementos.

Agora que já temos, vamos por mão no código.


Podemos ainda pegar pelo nome, classe, attributo, xpath, enfim…
fica a seu critério. Bastando somente mudar o By.Id para qual
função deseja utilizar.

No caso de Xpath, necessita ter um breve conhecimento no


assunto. Pois é utilizada exclusivamente para identificar ou
endereçar as partes de um documento XML. E convenhamos,
conulstar itens em XML é chato pra caramba :D

Mas indico essa extensão do Chrome para nos ajudar um


pouco: Relative XPath Helper

Conclusão
Mais simples que isso impossível. Vimos que podemos facilitar
diversos cenários de testes usando o Selenium. Num próximo post,
vamos fazer um exemplo mais intermediário usando algumas
coisas extras do Selenium.
Testes Automatizados
com Selenium
Parte II

Continuando o post anterior (veja aqui), falaremos hoje


sobre Actions.

Actions
É uma classe específica que automatiza interações avançadas com
o browser, como por exemplo movimentos do mouse, cliques,
pressionar as teclas, interações do menu de contexto, etc.

Para começo de tudo, esta classe está localizada no


namespaceOpenQA.Selenium.Interactions e o uso dela é
bem simples. Instanciamos a classe, passando no seu construtor
o WebDriver (objeto que ja vimos no post anterior).

Seria mais ou menos isso:

Webdriver webdriver = new Webdriver();


webdriver.Navigate().GoToUrl("sua_url");
Actions action = new Actions(webdriver);

Pronto, a partir de agora podemos usar os métodos de interação


do nosso Action. A lista completa dos métodos poderá ver aqui.
O intuito não é demonstrar todos os métodos. Vou criar um novo
post explicando alguns que talvez usemos mais no dia a dia.
Codando :)
Nosso amigo Actions, possui na sua lista de métodos, 3 caras
importantes: Build, Release e Perform.

 Build, irá construir a ação que queremos tomar num


determinado elemento.
 Release irá “matar” a ação criada ao elemento.
 Perform, executa a ação ou ações construída(s).
OBS: Perform deve ser incluído sempre que for executar uma
ação
Exemplo:
elemento_exemplo.Click().Perform();
elemento_exemplo.DoubleClick().Perform();

Demonstração
Vamos fazer uma demonstração com o site da Amazon, com o
seguinte cenário:

 Abrir o site da Amazon.com


 Ir ao menu principal
 Escolher um item qualquer
 Escolher um subitem, do item escolhido e clicar neste link
Primeiro exemplo
Vamos localizar o menu principal e usar o Action para fazer click
no mesmo.

Segundo exemplo
Iremos construir (usando Build) múltiplas ações em uma única
execução.
Para cada ação finalizada, iremos utilizar o Release para
“remover/matar” esta ação do elemento anterior.

Para o cenário proposto acima, usaremos a


função MoveToElement. Esta função irá fazer o trabalho de
mover nosso mouse pelo menu.
Em alguns casos, podemos que criar actions separados para
executar ações e ainda assim, utilizar pausas (Thread.Sleep por
exemplo), para continuar as outras ações. Veja abaixo:
Webdriver webdriver = new Webdriver();
webdriver.Navigate().GoToUrl("sua_url");
Actions action = new Actions(webdriver);
action
.MoveToElement(elemento1)
.ClickAndHold()
.Release()
.Build()
.Perform();
action
.MoveToElement(elemento2)
.Perform();

O método Build constrói uma sequência (uma pilha) de ações e


com isso ao chamar o Perform, sempre irá executar a primeira
ação criada.

Então quando for usar ações em sequências, não se esqueça de


remover a ação anterior.

Imagine isso (exemplo simples!!):

Webdriver webdriver = new Webdriver();


webdriver.Navigate().GoToUrl("sua_url");
Actions action = new Actions(webdriver);
action
.MoveToElement(botao)
.ClickAndHold()
.DoubleClick()
.Release()
.MoveToElement(caixa_de_texto)
.SendKeys("valor qualquer")
.Build()
.Perform();

Movemos o ponteiro do mouse para um botão na página, fizemos


um clique e “seguramos” o botão do mouse. Depois demos um
duplo clique e usamos o Release após executar as ações. Em
seguida, movemos para uma caixa de texto e escrevemos algo nela.
Costruimos todas essas ações e executamos de uma única vez.

Conclusão
Bem, acho que deu pra explicar mais ou menos o uso da
classe Actions. Esta classe nos permite fazer uma série de coisas
interessantes e usaremos em outros momentos.
Testes Automatizados
com Selenium
Parte III

Waits
Não poderia continuar os posts sem falar de Waits. Mas que
diabos é Waits? Esse cara serve para que a execução da tarefa
ocorra em uma certa quantidade de tempo antes de continuar com
o próximo passo. Um exemplo bem comum disso são as
requisições AJAX (execuções assíncronas), um botão que habilita
após preencher um campo, etc.

No Selenium, existem 2 tipos de Waits: Implicit Wait e Explicit


Wait.
A documentação diz para não utilizar as opções ao mesmo
tempo, pois pode causar tempos de espera imprevisíveis.

Implicit Waits
Uma espera implícita informa ao WebDriver para pesquisar na
página, um elemento (ou elementos) por um certo período de
tempo. A configuração padrão é 0 (zero). Uma vez definida, a
espera implícita é usada para a vida da instância do WebDriver.

O WebDriver possui um método chamado ImplicityWait que


especifica a quantidade de espera por qualquer comando no
restante do código, onde se um elemento ainda não está
disponível, ele aguarda até o tempo definido no comando. O
parâmetro dele usa o TimeSpan.

driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1
0));
var element = driver.FindElement(By.Id("id_element"));

Explicit Waits
É uma forma de inserir esperas através de comandos específicos.
Existem 2 tipos de esperas explícitas: WebDriverWait e Fluent
Waits.

WebDriverWait é aplicado em determinado elemento com


condição e tempo. Ele possui 2 construtores, mas iremos usar
somente o um. O primeiro construtor deste objeto recebe
um WebDriver e um TimeSpan. Este TimeSpan pode ser passado
segundos, minutos, horas etc.

No caso do WeDriverWait, será preciso instalar a


biblioteca Selenium.Support, que irá se integrar ao
Selenium.WebDriver.

install-package Selenium.Support

Abaixo temos uma chamada do método:

var wait = new WebDriverWait(webdriver,


TimeSpan.FromSeconds(10));
Ele também pode lançar exceção quando o elemento não é
encontrado, em combinação com a classe ExpectedCondition.
Esta classe possui vários métodos estáticos para diversos tipos de
tratamento (dê uma olhadinha aqui).

No exemplo abaixo, usaremos a ExpectedCondition para


satisfazer 3 ocasiões: se existir um elemento, se um outro estiver
visível ou se um elemento estiver visível e habilitado para ser
clicado. Satisfazendo cada opção, irá retornar o elemento, caso
contrário irá subir uma exceção.

Fluent Waits
É outro tipo de espera explícita onde você pode definir a pesquisa
e ignorar a exceção para continuar com a execução das ações caso
o elemento não seja encontrado. No C# não existe uma classe
específica como no Java, onde se faz de forma fluente toda a
configuração. (veja aqui sobre FluentWait com Java)

Mas, podemos adequar a nossa necessidade:

IWebdriver webdriver = new ChromeDriver();


var wait = new WebDriverWait(webdriver,
TimeSpan.FromSeconds(10));
wait.Message = "Time has expired";
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

Conclusão
Afinal, a espera implícita nos permite “burlar”, mascarando os
erros reais. Ignora tipos específicos de excepção, como por
exemplo NoSuchElementExceptions. Não seria interessante
usá-la no projeto. Inclusive todos recomendam fortemente não
utilizar. Basta o time do Selenium remover esta opção, já
ajudaria! :o)

A sugestão seria usar a Explicit Wait, por te dar uma maior


segurança ao localizar elementos. Além disso, pode ser utilizado
com o suporte da classe ExpectedConditions que nos ajuda
muito na busca de elementos e tratamentos específicos.
Testes Automatizados
com Selenium
Parte IV

Continuando a saga dos nossos testes automatizados, falamos


anteriormente sobre Actions e Wait. Hoje falaremos de mais
umas coisinhas : executar Javascript, usar a
classe SelectElement (dropdown ou combobox como queira
chamar) e por fim, fazer uma Screenshot (captura de tela).

Criando método Javascript


Primeiro vamos uma pequena explicação: Iremos usar a
interface IJavaScriptExecutor. Ela tem o papel, exclusivo, de
executar javascript. Seja ele retornando valor ou não.

 Para um elemento HTML, este método retorna um


IWebElement.
 Para número, um Int64 será retornado.
 Para um bool, um valor booleano será retornado.
 Para todos os outros casos, uma String será retornada.
 Se o valor é nulo ou não há valor de retorno, será retornado
nulo.
 E por fim, para um array, a interface verifica o primeiro
elemento e tenta retornar uma Lista <T> desse tipo, seguindo
as regras acima.
As listas aninhadas não são suportadas.

Esta interface funciona da seguinte maneira:

IJavaScriptExecutor js = (IJavaScriptExecutor)Webdriver;
ou
IJavaScriptExecutor js = Webdriver as IJavaScriptExecutor;

Ela deverá fazer um cast (conversão de tipo) do WebDriver, para


assim conseguirmos enxergar os seus métodos que são
2: ExecuteScript e ExecuteScriptAsync. Ambos retornam
um Object.
Nas referências, coloco um link o StackOverflow falando sobre
eles e com exemplos. Vale a pena dar uma olhadinha.

Iremos criar um método que irá receber um IWebElement e


executará um script Javascript, mas não retornará nada. Somente
execução. Pois, usaremos uma dica muito usada nos testes
automatizaos que é de marcar o elemento com borda de uma cor
específica.

public void HighlightElement(IWebElement element)


{
var script = @"arguments[0].style.cssText = ""border-
width: 2px; border-style: solid; border-color: red"";";

IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].style.border='2px solid
red'", element);
}
Usando CSS diretamente via javascript, apliquei 2 pixels de borda
e a informei a cor vermelha.
Por que usei arguments[0]?
O arguments é uma variável local disponível dentro de todas as
funções. Este objeto é um Array.
Imagine criar uma função de soma (exemplo muito tosco este,
somente para exemplificar):

function sumNumbers(x, y)
{
var n1 = arguments[0];
var n2 = arguments[1];
return (n1 + n2);
}
Com o arguments, podemos pegar esses valores de x e y.
Dê uma olhadinha aqui nesta documentação.

Usando nosso HighlightElement

var webdriver = new ChromeDriver();


var button = webdriver.FindElement(By.Id("id_button"));
HighlightElement(button);

SelectElement
Esta classe manipula as opções em um elemento HTML de
seleção. O famoso dropdown ou combobox. Ela é muito simples de
utilizar.

 Primeiro localizamos o elemento (do tipo select option).


 Instanciamos a classe SelectElement e passamos no construtor
dela o elemento encontrado.

var webdriver = new ChromeDriver();


var element = webdriver.FindElement(By.Id("id_dropdown"));
SelectElement dropdown = new SelectElement(element);

Ela possui diversos métodos, mas usaremos os mais comuns. Veja


abaixo:

Código HTML

<!DOCTYPE html>
<html>
<body>
<select id="id_dropdown">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</body>
</html>

Código C#

var webdriver = new ChromeDriver();


var element = webdriver.FindElement(By.Id("id_dropdown"));
SelectElement dropdown = new SelectElement(element);
var drop1 = dropdown.SelectIndex(2);
var drop2 = dropdown.SelectValue("audi");
var drop3 = dropdown.SelectText("Saab");

Então… peguei o valor na posição 2 do índice, ou seja o Opel.


Depois por valor e por texto.
Screenshot (Capturando imagens)
Acredito que essa parte é uma das mais simples de todas. Usando
cast da interface ITakesScreenshot com WebDriver, este obtém
um método de captura de tela chamado GetScreenshot.

Este método cria um objeto que contém um outro método


chamado SaveAsFile, qual recebe uma string (nome do
arquivo) e um
enumerador ScreenshotImageFormat (ou ImageFormat).

Esta segunda opção vem da


biblioteca System.Drawing.Imaging. Ambas irão nos mostrar
os formatos de imagens suportados. Dê uma olhadinha aqui.

Vejamos o código abaixo:

var webdriver = new ChromeDriver();


var photo = ((ITakesScreenshot)wedriver).GetScreenshot();
photo.SaveAsFile("c:\\photo.jpeg", ScreenshotImageFormat.Jpeg);

Também poderíamos fazer de uma forma mais direta:

var webdriver = new ChromeDriver();


webdriver.TakeScreenshot().SaveAsFile("c:\\photo.jpeg",
ScreenshotImageFormat.Jpeg);
Conclusão
Foram dicas rápidas para podermos usar em diversos cenários. E
espero que tenha ajudado no entendimento. Valeu e até o próximo
post. 😮

Referências
IJavaScriptExecutor.ExecuteScript Method
Executes JavaScript in the context of the currently selected frame or
window.seleniumhq.github.io
WebDriver executeAsyncScript vs executeScript
What is the difference between executeAsyncScript and executeScript? How can i use
event such as window.onload? I tried…stackoverflow.com
SelectElement Class
Provides a convenience method for manipulating selections of options in an HTML
select element.seleniumhq.github.io
ITakesScreenshot Interface
Defines the interface used to take screen shot images of the screen.seleniumhq.github.io
Selenium + SpecFlow + NUnit
+ ExtentReports
Reportando a execução dos testes

Olá tudo bem? Hoje vou explicar e exemplificar o uso


do ExtentReports, esta API interessante que nos oferece a
criação de relatórios interativos e também nos dá uma Dashboard,
visualizações gráficas, captura de tela e até envio dos resultados
por email. Tudo isso em formato HTML.

Além disso, pode ser configurada para suportar Java e .NET nos
principais frameworks de testes existentes. Também é permitido
registrar todos os passos dos testes num Report Server usando o
banco MongoDB. Para isso, ele utiliza uma biblioteca chamada
Klov. Mas, não iremos abordar neste momento.

Existem 2 versões desta API que são Community e


a Professional e que sinceramente não sei quanto custa a versão
paga (pelo menos o site não mostra). Para mais informações clique
neste link.

No entanto, a versão Community já nos atende em muita coisa e


por isso vamos conhecê-la na prática!

Criando o projeto de testes NUnit


Eu estou utilizado o Visual Studio 2017, mas fica a seu critério
utilizar o Visual Studio Code.

Nossos pacotes principais serão o Selenium, Specflow, e vamos


usar o Chrome como browser.

Vamos criar um projeto onde iremos pesquisar um produto


qualquer na Amazon, selecioná-lo e depois clicar em comprar.
Muito simples. Nada de login ou algo parecido.

 Crie um projeto de testes comum, eu chamei


de ExtentReportAmazon
 Vamos instalar alguns pacotes:

install-package Nunit
install-package NUnit3TestAdapter
install-package Specflow
install-package SpecFlow.NUnit
install-package Selenium.WebDriver
install-package Selenium.WebDriver.ChromeDriver
install-package ExtentReports

Tudo pronto! Vamos Criar algumas pastas para organizar nosso


projetinho. Eu deixei com a seguinte configuração:
 Common → Vão conter 2 classes, uma para configuração e
injeção de dependência do WebDriver e a outra contendo
um Hook (veremos mais abaixo do que se trata)
 ExtentionMethods → Como o nome já diz, serão métodos de
extensão, mas para utilizar com o Hook. Na verdade criei para
facilitar minha vida.
 Features → A feature criada pelo SpecFlow
 Pages → Aqui vamos criar uma classe simples seguindo o
Pattern Page Object Model
 Steps → Os passos que foram configurados na feature, ou seja,
as ações que serão executadas

Abaixo está o código fonte de cada classe:

A primeira será a Boostrapper. O SpecFlow nos oferece uma


interface chamada IObjectContainer que é automaticamente
injetável no construtor e ela nos ajudará a registrar/resolver a
dependência do IWebDriver, que no nosso caso usaremos
o ChromeDriver.

Utilizando Hooks
O SpecFlow tem um cara que nos ajuda em algumas coisas
interessantes, o nome dele é Hooks. Os Hooks são event bindings,
ou seja, pode ser usado, disparado, para executar um evento em
um momento específico, como por exemplo: executar uma função
antes de executar os testes ou depois de uma feature criada, enfim!

Para usar Hooks, precisamos adicionar o atributo Binding na


classe Hook e usar os atributos mais comuns: BeforeFeature,
BeforeScenario, AfterTestRun, AfterStep dentre outros. Dê uma
olhada no que se trata de Hooks e na lista de atributos que
podemos usar aqui.

Exemplo básico:

[Binding]
public class MeuHook
{
[AfterTestRun]
public void SalvarArquivoTexto()
{
// seu codigo aqui
}
}

Toda vez que você executar seu teste , tendo uma classe Hook para
fazer determinados processos, automaticamente irá passar por
esse trecho de código.

Abaixo o nosso Hook. Criei a classe com esse nome para nosso
exemplo. Vou explicar o seu conteúdo:

 O ExtentReports trabalha com nodos, esses nodos são “seções”


que o seu relatório terá. No SpecFlow, essas seções podemos
chamar de Feature, Scenario e Steps. Então, essas informações
do SpecFlow irão ser anexadas ao relatório para que o
ExtentReport crie camadas de informações contento o nome do
seu teste, o que ele irá fazer, os passos que estão sendo
executados, se tiveram erros ou falhas etc.

 Agora temos a classe de Extension Methods:

 Nosso arquivo de Feature será assim bem simples. Vamos abrir


o site da Amazon, pesquisar por Dell XPS, selecionar o
primeiro item da lista de produtos, adicionar ao carrinho e
verificar se tem 1 item adicionado.

Feature: Amazon Buy Dell XPS

Scenario: Buy a Dell XPS Laptop in Amazon website


Given I open Amazon website
And I search by Dell XPS
And I press enter key for submit
And I choose the first item of list
When I click in Add to Cart button
Then Must have one item in cart

 Agora criamos o nosso AmazonPage, uma classe já pré-


configurada para acessar os objetos DOM da página da Amazon
e executar algumas ações.

 Por fim a nossa classe de Steps chamada de


AmazonBuyDellXPS.

Executando
Vamos então executar o teste e vamos ver o resultado! Por aqui
não deu erro algum, mas podemos simular um erro para que nosso
Report mostre onde foi.
Agora com erro…

Adicionei no útimo Step que a quantidade no carrinho é igual a 2


para forçar um erro simples:

Assert.AreEqual(expected, 2);
Conclusão
Foi um exemplo simples, nada de tão complexo. Mas dá pra
vermos que o ExtentReports nos ajuda nesse processo de
relatórios. Existem várias outras configurações desta API, mas não
entrei em tantos detalhes. Dê uma fuçada para conhecer um pouco
mais. Vale apena!

Deixo aqui uma informação:

 Como a versão Community não envia emails, nem captura tela


por exemplo. Mas, podemos enviar manualmente o conteúdo
HTML por email. Faça essa experiência.
O código fonte se encontra nas referências. Valeu e até a próxima!
Parametrizando Testes
Unitários
Aplicando nos frameworks MsTest, NUnit e xUnit

Olá tudo bem? Temos 3 principais concorrentes de framework


para testes unitários (ou testes de unidade), são eles:

MsTest
O Visual Studio Unit Testing Framework (MS Test), parte
integrante da própria IDE de desenvolvimento da Microsoft.

NUnit
Framework open source, foi portado inicialmente JUnit (um dos
primeiros frameworks para testes unitários na plataforma Java).

xUnit
Já o xUnit, é uma ferramenta de teste de unidade gratuita,
também open source, foi escrito pelo inventor original do NUnit
v2, é o mais novo framework para testes unitários em .NET.

Todos os citados suportam .NET Core e nosso projeto de testes


será baseado nele.
Não venho aqui explicar como se criam testes unitários complexos
ou “mockar” algum objeto etc. A idéia é utilização de
parametrização nos 3 frameworks citados.
Iniciando
Bem… na construção de cada teste, cada framework tem suas
particularidades como assinatura da classe, do método,
configurações etc. Uma delas é nos permitir passar mais
parâmetros de entrada para criarmos nossos testes. Para os testes,
usaremos uma classe simples de Calculadora com uma função de
soma, nada complexo.

Venho demonstrar o uso desses “multi-parâmetros” em cada um


desses frameworks. Quando falo multi-parâmetros, estou falando
de passar várias opções de entrada para seus testes, como se fosse
um array ou uma lista de dados a serem testados. Isso fará um
laço/repetição no método de teste até que cubra todos os valores
informados. Vamos lá:

MsTest
Desde a versão Visual Studio 2012 Update 1, é possível criar
testes com vários parâmetros de entrada, adicionando à
assinatura do método os
attributos DataTestMethod, DataRow.

DataTestMethod é um atributo que nos permite executar vários


testes ao mesmo tempo e o DataRow para especificar quais são
os parâmetros/valores de entrada que queremos testar.

NUnit
Para esse framework, crie um projeto Class Library (.Net Core) e
não se esqueça de instalar os pacotes abaixo:

install-package Microsoft.NET.Test.Sdk
install-package NUnit
install-package NUnit3TestAdapter
xUnit
Já com nosso amigo xUnit, temos alguns outros benefícios
interessantes, como por exemplo além de testar múltiplos
parâmetros, podemos testar uma classe inteira ou um método de
uma classe específica, ambos como parâmetro. Mas antes, crie um
projeto de testes do tipo xUnit, ou um projeto Class Library (.Net
Core) e instale os pacotes abaixo:

install-package xunit
install-package xunit.runner.visualstudio

Vejamos um exemplo parecido com o anteriores:

Agora um exemplo do que comentamos acima: testar uma classe


inteira ou um método de uma classe específica, ambos como
parâmetro.

Criei duas classes. Uma classe chamada CalculatorTest.cs com


um método chamado ParametersToSum. Esse método irá me
retornar um IEnumerable com um array de objetos contendo a
soma dos 2 números mais o resultado de cada array de objeto. A
outra classe CalculatorTestData, irá herdar da interface
IEnumerable.

Agora vou invocar esse método usando


o MemberData e MemberType. O MemberData especifica qual
o método que estou desejando testar dentro da classe. O método
que for chamado pelo MemberData deve ser do
tipo static e público:

public class CalculatorTest


{
public static IEnumerable<object[]> ParametersToSum()
{
return new List<object[]>
{
new object[] {10, 20, 30} // soma de 10 + 20 = 30,
new object[] {12, 2, 14} // soma de 12 + 12 = 14
};
}
}

No segundo caso, usaremos um objeto herdado da


interface IEnumerable e claro, deveremos implementar os seus
métodos:

public class CalculatorTestData : IEnumerable<object[]>


{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] {10, 20, 30};
yield return new object[] {12, 2, 14};
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

Neste caso estou usando o atributo ClassData. Este atributo


fornece uma fonte com os dados provenientes de uma classe que
deve implementar IEnumerable<object[]>.

Acho que dá pra entender um pouco sobre as 3 diferenças. Deixo


também uma pequena referência com um quadro comparativo
para curiosidade. Não venho aqui dizer qual é o melhor, mas
exemplificar que ambos conseguem entregar a mesma proposta
que foi dita neste post.
Por enquanto é só. Obrigado e até mais!

Referências
Comparing xUnit.net to other frameworks > xUnit.net
xUnit.net does not require an attribute for a test class; it looks for all test methods in all public
(exported)…xunit.github.io
Parametrizando Testes
Unitários
Aplicando nos frameworks MsTest, NUnit e xUnit

Olá tudo bem? Temos 3 principais concorrentes de framework


para testes unitários (ou testes de unidade), são eles:

MsTest
O Visual Studio Unit Testing Framework (MS Test), parte
integrante da própria IDE de desenvolvimento da Microsoft.

NUnit
Framework open source, foi portado inicialmente JUnit (um dos
primeiros frameworks para testes unitários na plataforma Java).

xUnit
Já o xUnit, é uma ferramenta de teste de unidade gratuita,
também open source, foi escrito pelo inventor original do NUnit
v2, é o mais novo framework para testes unitários em .NET.

Todos os citados suportam .NET Core e nosso projeto de testes


será baseado nele.
Não venho aqui explicar como se criam testes unitários complexos
ou “mockar” algum objeto etc. A idéia é utilização de
parametrização nos 3 frameworks citados.
Iniciando
Bem… na construção de cada teste, cada framework tem suas
particularidades como assinatura da classe, do método,
configurações etc. Uma delas é nos permitir passar mais
parâmetros de entrada para criarmos nossos testes. Para os testes,
usaremos uma classe simples de Calculadora com uma função de
soma, nada complexo.

Venho demonstrar o uso desses “multi-parâmetros” em cada um


desses frameworks. Quando falo multi-parâmetros, estou falando
de passar várias opções de entrada para seus testes, como se fosse
um array ou uma lista de dados a serem testados. Isso fará um
laço/repetição no método de teste até que cubra todos os valores
informados. Vamos lá:

MsTest
Desde a versão Visual Studio 2012 Update 1, é possível criar
testes com vários parâmetros de entrada, adicionando à
assinatura do método os
attributos DataTestMethod, DataRow.

DataTestMethod é um atributo que nos permite executar vários


testes ao mesmo tempo e o DataRow para especificar quais são
os parâmetros/valores de entrada que queremos testar.

NUnit
Para esse framework, crie um projeto Class Library (.Net Core) e
não se esqueça de instalar os pacotes abaixo:

install-package Microsoft.NET.Test.Sdk
install-package NUnit
install-package NUnit3TestAdapter
xUnit
Já com nosso amigo xUnit, temos alguns outros benefícios
interessantes, como por exemplo além de testar múltiplos
parâmetros, podemos testar uma classe inteira ou um método de
uma classe específica, ambos como parâmetro. Mas antes, crie um
projeto de testes do tipo xUnit, ou um projeto Class Library (.Net
Core) e instale os pacotes abaixo:

install-package xunit
install-package xunit.runner.visualstudio

Vejamos um exemplo parecido com o anteriores:

Agora um exemplo do que comentamos acima: testar uma classe


inteira ou um método de uma classe específica, ambos como
parâmetro.

Criei duas classes. Uma classe chamada CalculatorTest.cs com


um método chamado ParametersToSum. Esse método irá me
retornar um IEnumerable com um array de objetos contendo a
soma dos 2 números mais o resultado de cada array de objeto. A
outra classe CalculatorTestData, irá herdar da interface
IEnumerable.

Agora vou invocar esse método usando


o MemberData e MemberType. O MemberData especifica qual
o método que estou desejando testar dentro da classe. O método
que for chamado pelo MemberData deve ser do
tipo static e público:

public class CalculatorTest


{
public static IEnumerable<object[]> ParametersToSum()
{
return new List<object[]>
{
new object[] {10, 20, 30} // soma de 10 + 20 = 30,
new object[] {12, 2, 14} // soma de 12 + 12 = 14
};
}
}

No segundo caso, usaremos um objeto herdado da


interface IEnumerable e claro, deveremos implementar os seus
métodos:

public class CalculatorTestData : IEnumerable<object[]>


{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] {10, 20, 30};
yield return new object[] {12, 2, 14};
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

Neste caso estou usando o atributo ClassData. Este atributo


fornece uma fonte com os dados provenientes de uma classe que
deve implementar IEnumerable<object[]>.

Acho que dá pra entender um pouco sobre as 3 diferenças. Deixo


também uma pequena referência com um quadro comparativo
para curiosidade. Não venho aqui dizer qual é o melhor, mas
exemplificar que ambos conseguem entregar a mesma proposta
que foi dita neste post.
Por enquanto é só. Obrigado e até mais!

Referências
Comparing xUnit.net to other frameworks > xUnit.net
xUnit.net does not require an attribute for a test class; it looks for all test methods in all public
(exported)…xunit.github.io

Você também pode gostar