Guia Básico de TDD em C#.Net

Documentos relacionados
Teste Unitários com NUnit. Anderson Martiniano da Rocha

Introdução ao Desenvolvimento de Aplicativos Android

IDES E PROGRAMAÇÃO. Prof. Dr. Cláudio Fabiano Motta Toledo PAE: Maurício A Dias

Modelo de Instalação e configuração do token 5100 e 5110.

Consulta de endereço através do Cep

Versão 4.0. Ecoscard Serviços de Suporte em Cartões Inteligentes Ltda Confidencial 1

Análise e Projeto Orientados a Objetos

05 Como utilizar POO no ambiente gráfico do C#?

DESENVOLVIMENTO DE SOFTWARE PARA INTERNET LABORATÓRIO 4 PROF. EMILIO PARMEGIANI

Implementando classes em C# Curso Técnico Integrado em Informática Fundamentos de Programação

AULA 2 VISÃO BÁSICA DE CLASSES EM PHP

Laboratório de programação II

Aplicação MVC com Class Library

Criando um Editor de Diagramas com Sirius

Automação em Telas. Desenvolvimento IBM Maximo nível 1. Leonardo Almeida Bastos Versão 1.0

Testes Unitários com JUnit

INSTALAÇÃO DO CLIENTE LOTUS NOTES ROTEIRO DE INSTALAÇÃO E CONFIGURAÇÃO

Procedimentos para Atualização Sisloc

(INFORMAÇÕES PARA LABORATÓRIOS VIRTUAIS) Nome do laboratório: Laboratório de Programação (INFORMAÇÕES PARA FERRAMENTA)

nome = n; cargo = c; salario = s; public void print() { System.out.println(nome cargo salario); public void aumento( double fator){

Configurador do JBOSS. TOTVS Datasul 11. Alerta

MANUAL DO INSTALADOR DE CURSOS VERSÃO

COMPORTAMENTOS - Observações

POO Documentation. Release 1.0. Felipe Dau e Francisco Pereira Junior

Instalação JDK 10/03/2017

Fábrica de Noobs Reloaded Sistemas Operacionais Instalando e Utilizando o VirtualBox

DISTRIBUINDO SUA APLICAÇÃO

Desenvolvendo aplicações Java

Usando o Eclipse - Fundamentos. Professor Vicente Paulo de Camargo

Índice. 1. Introdução Instalação: Eclipse e Android Primeira aplicação em Android... 11

MANUAL DO INSTALADOR DE CURSOS VERSÃO (64 bits) - BETA

Tratamento de Erros. Sérgio Luiz Ruivace Cerqueira

Guia de instalação Impressora Térmica EPSON TM-88IV (Linux)

Sobre o Visual C

Instalação JDK. Joyce França. Professora de Ciência da Computação - IFNMG

Guia de Instalação e Inicialização. Para DataPage+ 2012

O JUnit permite a realização de testes de unidades, conhecidos como "caixa branca", facilitando assim a correção de métodos e objetos.


Linguagem de Programação II Implementação

JUnit. Facilitando o desenvolvimento e execução de testes unitários em código java. Peterson Rodrigues

Tutorial de Instalação Linux Ubuntu LTS

Instalando o Eclipse e o Android

Instalação do TextPad

Microsoft Word 2010 NORMA ABNT para Trabalhos Acadêmicos Conceitos Básicos

Programação Orientada a Objetos

Manual de instalação do Maple para Linux

Manual de Instrução: LG MG320c - Versão Windows LG MG320C

WINDOWS FORMS APPLICATION - Aplicação (Programa) que não usa a CONSOLE

Introdução ao C# com o Microsoft Visual Studio Community 2015

PRDS C#.Net Alexandre L. Silva

Tutorial de Instalação Linux Mint 19 Tara

MANUAL DO INSTALADOR DE CURSOS PORTÁTIL v.1.0

Selecione o WPF Application dentro de Templates > Visual C# > Windows

Como instalar Open Broadcaster Software (OBS) para transmitir em HD

Gerando um programa executável a partir de um módulo Python

Manual de Instalação Software de Cartão Inteligente SafeSign

Modificadores de Acesso e Atributos de Classe

SISCEL. Sistema de Controle de Exames Laboratoriais

Introdução à Ciência da Computação com Jogos Bruno Feijó - Esteban Clua - Fávio S. Corrêa da Silva

Figura 1: Eclipse criação de um Dynamic Web Project

Sistema SGPA-IFSP. Manual de Instalação

PCS Laboratório de Programação Orientada a Objetos 1a. Prova. 02 de Setembro de 2015

Criação de uma aplicação Web ASP.NET MVC 4

Usando VNC para instalar o CallManager da Cisco em um servidor remoto

Guia para o iniciante no Orthanc Para físicos-médicos, médicos e clínicos gerais.

Instalação Client Oracle 10g 32 e 64 bits

Classes e Objetos. Sintaxe de classe em Java

Encapsulamento e Métodos (Construtores e Estáticos) João Paulo Q. dos Santos

Conhecendo o Delphi 2010

TUTORIAL DE USO DO GIT JUNTO AO ECLIPSE

Instalação do Oracle VM Virtual Box

1 Introdução e Conceitos básicos

Linguagem de Programação II Programação Orientada a Objetos. Ambientes de Programação

MÓDULO FISCAL ELETRÔNICO MFE MANUAL DE INSTALAÇÃO

TUTORIAL DE INSTALAÇÃO DO AMBIENTE DE DESENVOLVIMENTO ANDROID NO UBUNTU

Programação Orientada a Objetos

Introdução à Engenharia ENG1000

Ferramenta Selenium. Programação Orientada a Objetos Prof Marcio Delamaro ICMC/USP

LÓGICA DE PROGRAMAÇÃO PARA ENGENHARIA TUTORIAL OPEN WATCOM: CRIANDO O PRIMEIRO PROGRAMA

Pacote de instalação dos componentes Selo Digital /SP

Usando o VMware Identity Manager Desktop. VMware Identity Manager 2.8 VMware Identity Manager 2.9.1

Lista de Exercícios da disciplina Aplicações de Linguagem de Programação Orientada a objetos

Manual Técnico. Instalação e Configuração do Reporting Services

Universidade Federal de Uberlândia Faculdade de Computação Programação Orientada a Objetos II Prof. Fabiano Dorça. Padrão Observer (Observador)

Passo-a-passo para desenvolver um Programa usando a Linguagem Python

Transcrição:

Guia Básico de TDD em C#.Net Confidencial DBServer, 2016 Página 1 de 34

Índice 1. Introdução 3 2. Definições 3 3. Exemplo básico 4 3.1 Criação do Projeto de Teste 4 3.2 Criação dos primeiros testes 6 3.3 Refatoração do código 12 4. Tipos de Assert 19 4.1 Assert.AreEqual 19 4.2 Assert.AreNotEqual 20 4.3 Assert.AreSame 20 4.4 Assert.AreNotSame 20 4.5 Assert.Fail 21 4.6 Assert.Inconclusive 21 4.7 Assert.IsTrue 21 4.8 Assert.IsFalse 22 4.9 Assert.IsInstanceOfType 22 4.10 Assert.IsNotInstanceOfType 22 4.11 Assert.IsNull 22 4.12 Assert.IsNotNull 22 5. Tipos de CollectionAssert 23 5.1 CollectionAssert.AreEqual 23 5.2 CollectionAssert.AreNotEqual 23 5.3 CollectionAssert.AllItemsAreUnique 23 5.4 CollectionAssert.Contains 23 5.5 CollectionAssert.DoesNotContain 24 Oposto de CollectionAssert.Contains. Erro! Indicador não definido. 5.6 CollectionAssert.ReferenceEquals 24 5.7 CollectionAssert.AllItemsAreNotNull 24 5.8 CollectionAssert.AllItemsAreInstancesOfType 24 5.9 CollectionAssert.IsSubsetOf 25 5.10 CollectionAssert.IsNotSubsetOf 25 Oposto de CollectionAssert.IsSubsetOf 25 6. ExpectedException 26 7. Nunit Framework 27 7.1 Instalação e configuração 27 7.2 Executando testes no Nunit 30 8. Fontes 34 Confidencial DBServer, 2016 Página 2 de 34

1. Introdução Este documento tem por finalidade apresentar o básico da metodologia TDD, bem como exemplos de sua utilização. 2. Definições TDD (Test Driven Development) é uma técnica que surgiu com o objetivo de produzir código confiável em menos tempo e com menos defeitos. No método tradicional de desenvolvimento o código é testado apenas no final da codificação, fazendo com que o desenvolvedor encontre muitos erros e necessite muito tempo debugando todo o código para tentar encontrar a razão e solucionar o problema e, frequentemente, encontrando novos erros resultantes da última correção realizada. O TDD, no entanto, traz uma nova abordagem: Teste primeiro, codifique depois. Ele se baseia no ciclo Vermelho-Verde-Refatora, que seria resumidamente: 1) Crie testes que garantam que o código funcione adequadamente. Como apenas os testes foram criados e nada foi codificado, os testes já iniciarão falhos. (Vermelho) 2) Após criar o teste, crie o código necessário para que o teste passe da forma mais simples possível e rode o teste novamente. (Verde) 3) Se o código passar no teste, então refatore o código aplicando boas práticas para torna-lo mais testável e repita o processo novamente. (Refatora) Vantagens: Código é testado constantemente, desde o início do projeto e não apenas no final. Erros são encontrados e resolvidos em sua origem. Para que o código seja testável, ele deve ser bem codificado, incentivando boas práticas de programação e forçando o desenvolvedor a usar seu raciocíno de forma mais elevada para evitar acoplamentos e dependências. Segurança para o desenvolvedor que sabe que qualquer erro será encontrado logo no início do desenvolvimento. Facilita a refatoração do código. Pode ser usado como documentação. Desvantagens: Desenvolvimento inicial mais lento, até desenvolvedor se adaptar a técnica. Necessidade de manutenção dos códigos de teste, além do código de produção. Confidencial DBServer, 2016 Página 3 de 34

3. Exemplo básico Como projeto de exemplo usaremos um projeto muito simples para a construção de um carro, que deverá seguir as seguintes regras de negócio: Deve possuir um motor Deve possuir duas portas Deve possuir quatro rodas 3.1 Criação do Projeto de Teste Crie um projeto do tipo Class Library no Visual Studio. Eu nomeei meu projeto como TDD.Domain. Confidencial DBServer, 2016 Página 4 de 34

Crie um novo projeto do tipo Test / Unit Test Project no Visual Studio. Eu nomeei meu projeto como TDD.Test: Criado o projeto, adicione referência ao projeto TDD.Domain no projeto TDD.Test: Confidencial DBServer, 2016 Página 5 de 34

3.2 Criação dos primeiros testes Baseando-se nas regras de negócio básicas, já podemos iniciar o desenvolvimento utilizando a metodologia TDD. Primeiro passo será a criação dos testes. Iniciaremos verificando se o carro possui um motor criando o método de teste DevePossuirMotor(), instanciando um objeto do tipo Carro e testando se o atributo Motor é vazio: Teste inicial /// <summary> /// Valida se atributo Motor da classe Carro não é nulo /// </summary> public void DevePossuirMotor() Carro carro = new Carro(); Assert.IsNotNull(carro.Motor); Para rodar o teste, basta clicar com o botão direito sobre o método ou sobre o nome da classe e selecionar Run Tests. Confidencial DBServer, 2016 Página 6 de 34

Ao tentar rodar este teste, recebemos um erro de compilação pois a classe Carro não existe, mas isto está correto pois a primeira etapa do TDD nos diz que devemos primeiro criar o teste e depois codificarmos da forma mais simples possível para fazer o teste passar. Então, vamos para a próxima etapa e iniciaremos a codificação de fato, criando a classe Carro e os demais objetos necessários (neste caso a classe Motor) para este teste ser aceito: public class Motor public double Potencia get; set; public string Combustivel get; set; public Motor() Criação das classes public class Carro public Motor Motor get; private set; public Carro() Sem o erro de compilação podemos rodar o teste, mas o teste irá falhar novamente já que o objeto Motor não foi inicializado: Confidencial DBServer, 2016 Página 7 de 34

Basta inicializarmos a propriedade Motor no construtor da classe Carro e testar novamente que o teste passará: Public Carro() Motor = new Motor(); Inicializando propriedade Nosso próximo passo será criar testes para validar se o carro possui 4 rodas e 2 portas. Novamente aqui os objetos Porta e Roda ainda não existem, bem como os atributos Portas e Rodas na classe Carro: Criando testes de quantidade de Portas e Rodas /// <summary> /// Valida se carro possui 4 rodas /// </summary> public void DevePossuirQuatroRodas() Carro carro = new Carro(); List<Roda> rodas = carro.rodas; Assert.AreEqual( 4, rodas.count ); /// <summary> /// Valida se carro possui 2 portas /// </summary> public void DevePossuirDuasPortas() Carro carro = new Carro(); List<Porta> portas = carro.portas; Assert.AreEqual( 2, portas.count ); Confidencial DBServer, 2016 Página 8 de 34

Testes prontos, vamos ao segundo passo codificar novamente, criando as classes e propriedades que foram identificadas no teste: public class Porta public bool EstaAberta get; set; public Porta() Criando classes e propriedades public class Roda public double Aro get; set; public Roda() public class Carro private List<Roda> _rodas; private List<Porta> _portas; public Motor Motor get; private set; public Lataria Lataria get; private set; public List<Roda> Rodas get return _rodas; public List<Porta> Portas get return _portas; public Carro() Motor = motor; Confidencial DBServer, 2016 Página 9 de 34

Lataria = lataria; _portas = new List<Porta>(); _rodas = new List<Roda>(); Ao executarmos o teste, obtivemos os erros abaixo, pois não incluímos nenhuma Porta ou Roda ao nosso Carro: Vamos incluir as portas e rodas em nosso carro, criando os métodos CriarPortas() e CriarRodas() e rodar o teste novamente, desta vez o teste passará: Incluindo portas e rodas no carro public class Carro private List<Roda> _rodas; private List<Porta> _portas; public Motor Motor get; private set; public Lataria Lataria get; private set; public List<Roda> Rodas get return _rodas; public List<Porta> Portas Confidencial DBServer, 2016 Página 10 de 34

get return _portas; public Carro() Motor = new Motor(); Lataria = new Lataria(); CriarRodas(); CriarPortas(); private void CriarPortas() _portas = new List<Porta>(); Porta portadireita = new Porta(); Porta portaesquerda = new Porta(); _portas.add( portadireita ); _portas.add( portaesquerda); private void CriarRodas() _rodas = new List<Roda>(); Roda rodadianteiradireita = new Roda(); Roda rodadianteiraesquerda = new Roda(); Roda rodatraseiradireita = new Roda(); Roda rodatraseiraesquerda = new Roda(); _rodas.add( rodadianteiradireita ); _rodas.add( rodadianteiraesquerda ); _rodas.add( rodatraseiradireita ); _rodas.add( rodatraseiraesquerda ); Confidencial DBServer, 2016 Página 11 de 34

3.3 Refatoração do código O terceiro princípio do TDD é a refatoração, tornar o código mais testável e, por consequência, tornar o código menos acoplado e mais coeso. Vamos então refatorar nosso código, iniciando pela criação de interfaces para cada um de nossos objetos e modificando os tipos dos objetos para interfaces ao invés de classes concretas dentro da classe Carro: public interface IRoda double Aro get; set; Criando interfaces public interface IPorta bool EstaAberta get; set; public interface ILataria string Cor get; set; public interface IMotor double Potencia get; set; string Combustivel get; set; public interface ICarro IMotor Motor get; set; List<IRoda> Rodas get; set; List<IPorta> Portas get; set; ILataria Lataria get; set; Fazendo classes implementarem e usarem interfaces public class Roda : IRoda public double Aro get; set; public Roda() Confidencial DBServer, 2016 Página 12 de 34

public class Porta : IPorta public bool EstaAberta get; set; public Porta() public class Lataria : ILataria public string Cor get; set; public Lataria() public class Motor : IMotor public double Potencia get; set; public string Combustivel get; set; public Motor() public class Carro : ICarro private List<IRoda> _rodas; private List<IPorta> _portas; public IMotor Motor get; private set; public ILataria Lataria get; private set; public List<IRoda> Rodas get return _rodas; Confidencial DBServer, 2016 Página 13 de 34

public List<IPorta> Portas get return _portas; public Carro() Motor = new Motor(); Lataria = new Lataria(); CriarRodas(); CriarPortas(); private void CriarPortas() _portas = new List<IPorta>(); IPorta portadireita = new Porta(); IPorta portaesquerda = new Porta(); _portas.add( portadireita ); _portas.add( portaesquerda); private void CriarRodas() _rodas = new List<IRoda>(); IRoda rodadianteiradireita = new Roda(); IRoda rodadianteiraesquerda = new Roda(); IRoda rodatraseiradireita = new Roda(); IRoda rodatraseiraesquerda = new Roda(); _rodas.add( rodadianteiradireita ); _rodas.add( rodadianteiraesquerda ); _rodas.add( rodatraseiradireita ); _rodas.add( rodatraseiraesquerda ); Confidencial DBServer, 2016 Página 14 de 34

Nosso código agora usa interfaces. Vamos adaptar nossos testes para utiliza-las: Aplicando interfaces em nosso teste /// <summary> /// Valida se atributo Motor da classe Carro não é nulo /// </summary> public void DevePossuirMotor() ICarro carro = new Carro(); Assert.IsNotNull(carro.Motor); /// <summary> /// Valida se carro possui 4 rodas /// </summary> public void DevePossuirQuatroRodas() ICarro carro = new Carro(); List<IRoda> rodas = carro.rodas; Assert.AreEqual( 4, rodas.count ); /// <summary> /// Valida se carro possui 2 portas /// </summary> public void DevePossuirDuasPortas() ICarro carro = new Carro(); List<IPorta> portas = carro.portas; Assert.AreEqual( 2, portas.count ); Outra refatoração que temos que realizar aqui é aplicar os conceitos de Injeção de Dependência e Inversão de Controle, que trazem algumas vantagens como: Desacoplamento de nosso código, pois não é necessário modificar uma classe sempre que uma de suas dependências for modificada. Facilita a reutilização de código. Torna o código testável. Vamos aplicar estes conceitos em nossa classe Carro, incluindo no construtor da classe as dependências Motor e Lataria. Desta forma, um Carro nunca poderá ser criado se não tiver um Motor e Lataria e principalmente nunca será o responsável por decidir como o Motor e Lataria serão criados, Confidencial DBServer, 2016 Página 15 de 34

essa responsabilidade será de quem criar o Carro. Outra vantagem é que um Carro poderá ser criado com diversos motores e latarias sem precisar alterar sua implementação: public class Carro : ICarro private List<IRoda> _rodas; private List<IPorta> _portas; Aplicando Injeção de Dependência public IMotor Motor get; private set; public ILataria Lataria get; private set; public List<IRoda> Rodas get return _rodas; public List<IPorta> Portas get return _portas; public Carro(IMotor motor, ILataria lataria) Motor = motor; Lataria = lataria; CriarRodas(); CriarPortas(); private void CriarPortas() _portas = new List<IPorta>(); IPorta portadireita = new Porta(); IPorta portaesquerda = new Porta(); _portas.add( portadireita ); _portas.add( portaesquerda); private void CriarRodas() _rodas = new List<IRoda>(); IRoda rodadianteiradireita = new Roda(); Confidencial DBServer, 2016 Página 16 de 34

IRoda rodadianteiraesquerda = new Roda(); IRoda rodatraseiradireita = new Roda(); IRoda rodatraseiraesquerda = new Roda(); _rodas.add( rodadianteiradireita ); _rodas.add( rodadianteiraesquerda ); _rodas.add( rodatraseiradireita ); _rodas.add( rodatraseiraesquerda ); Com a injeção de Dependência aplicada, agora o responsável por criar os objetos Motor e Lataria é nosso método de teste: Aplicando Injeção de Dependência em nosso teste /// <summary> /// Valida se atributo Motor da classe Carro não é nulo /// </summary> public void DevePossuirMotor() IMotor motor = new Motor(); ILataria lataria = new Lataria(); ICarro carro = new Carro(motor, lataria); Assert.IsNotNull(carro.Motor); /// <summary> /// Valida se carro possui 4 rodas /// </summary> public void DevePossuirQuatroRodas() IMotor motor = new MotorY(); ILataria lataria = new Lataria(); ICarro carro = new Carro(motor, lataria); List<IRoda> rodas = carro.rodas; Assert.AreEqual( 4, rodas.count ); /// <summary> /// Valida se carro possui 2 portas /// </summary> public void DevePossuirDuasPortas() IMotor motor = new Motor(); ILataria lataria = new Lataria(); Confidencial DBServer, 2016 Página 17 de 34

ICarro carro = new Carro(motor, lataria); List<IPorta> portas = carro.portas; Assert.AreEqual( 2, portas.count ); Para melhor exemplificar o uso da Injeção de Dependência e Inversão de Controle criei a classe MotorY, que também implementa a interface IMotor. No método DevePossuirQuatroRodas() o Carro foi criado com o motor MotorY, enquanto que nos métodos DevePossuirMotor() e DevePossuirDuasPortas() o Carro foi criado com o motor Motor, não sendo necessário em nenhum momento alterar a implementação da classe Carro para cria-lo e testa-lo com um motor diferente. Confidencial DBServer, 2016 Página 18 de 34

4. Tipos de Assert 4.1 Assert.AreEqual Verifica se dois valores são iguais. Para o tipo string, o Assert.AreEqual possui os parâmetros ignorecase e cultureinfo. Para os tipos double e float o Assert.AreEqual possui o parâmetros delta. Assert.AreEqual public void TestAssertEqual() IMotor motor = new Motor(); ILataria lataria = new Lataria(); ICarro carro = new Carro( motor, lataria ); List<IPorta> portas = carro.portas; Assert.AreEqual( 2, portas.count, "Erro encontrado [0]", DateTime.Now ); /// <summary> /// Assert.AreEqual para tipo string /// </summary> public void TestAssertEqualString() string str1 = "Valor string"; string str2 = "Valor string"; //Sem mensagem formatada de Erro Assert.AreEqual( str1, str1 ); //Com IgnoreCase Assert.AreEqual( str1, str1, true ); //Com IgnoreCase Assert.AreEqual( str1, str1, true, System.Globalization.CultureInfo.GetCultureInfo(1) ); //Com mensagem formatada de Erro Assert.AreEqual( str1, str2, "Erro encontrado [0]", DateTime.Now ); //Completa Assert.AreEqual( str1, str1, true, System.Globalization.CultureInfo.GetCultureInfo( 1 ), "Erro encontrado [0]", DateTime.Now ); Confidencial DBServer, 2016 Página 19 de 34

/// <summary> /// Assert.AreEqual para tipo double /// </summary> public void TestAssertEqualDouble() double dbl1 = 1.25; double dbl2 = 1.25; double delta = 0.5; //Sem mensagem formatada de Erro Assert.AreEqual( dbl1, dbl1 ); //Com delta Assert.AreEqual( dbl1, dbl1, delta ); //Com mensagem formatada de Erro Assert.AreEqual( dbl1, dbl2, "Erro encontrado [0]", DateTime.Now ); //Completa Assert.AreEqual( dbl1, dbl1, delta, "Erro encontrado [0]", DateTime.Now ); 4.2 Assert.AreNotEqual Oposto de AreEqual. 4.3 Assert.AreSame Verifica se duas variaveis apontam para o mesmo objeto public void TestAreSame() IMotor motor = new Motor(); ILataria lataria = new Lataria(); //Sem mensagem formatada de Erro Assert.AreSame( motor, lataria); Assert.AreSame //Com mensagem formatada de Erro Assert.AreSame( motor, lataria, "Erro encontrado [0]", DateTime.Now ); 4.4 Assert.AreNotSame Oposto de AreSame. Confidencial DBServer, 2016 Página 20 de 34

4.5 Assert.Fail Sempre falha o teste sem validar nada. public void TestFail() //Sem mensagem formatada de Erro Assert.Fail(); Assert.Fail //Com mensagem formatada de Erro Assert.Fail( "Erro encontrado [0]", DateTime.Now ); 4.6 Assert.Inconclusive Indica que o Assert não pode ser verificado public void TestInconclusive() //Sem mensagem formatada de Erro Assert.Inconclusive(); Assert.Inconclusive //Com mensagem formatada de Erro Assert.Inconclusive( "Erro encontrado [0]", DateTime.Now ); 4.7 Assert.IsTrue Valida se determinada condição é verdadeira Assert.IsTrue public void TestIsTrue() string str1 = "Valor string"; string str2 = "Valor string"; //Sem mensagem formatada de Erro Assert.IsTrue( str1 == str2 ); //Com mensagem formatada de Erro Assert.IsTrue( str1 == str2, "Erro encontrado [0]", DateTime.Now ); Confidencial DBServer, 2016 Página 21 de 34

4.8 Assert.IsFalse Oposto de IsTrue. 4.9 Assert.IsInstanceOfType Valida se objeto é de determinado tipo public void TestIsInstanceOf() string str2 = "Valor string 2"; Assert.IsInstanceOfType //Sem mensagem formatada de Erro Assert.IsInstanceOfType(str2, typeof(string)); //Com mensagem formatada de Erro Assert.IsInstanceOfType( str2, typeof( string ), "Erro encontrado [0]", DateTime.Now ); 4.10 Assert.IsNotInstanceOfType Oposto de IsInstanceOfType. 4.11 Assert.IsNull Valida se valor é nulo public void TestIsNull() string str2 = null; //Sem mensagem formatada de Erro Assert.IsNull(str2); Assert.IsNull //Com mensagem formatada de Erro Assert.IsNull( str2, "Erro encontrado [0]", DateTime.Now ); 4.12 Assert.IsNotNull Oposto de IsNull Confidencial DBServer, 2016 Página 22 de 34

5. Tipos de CollectionAssert 5.1 CollectionAssert.AreEqual Valida se itens são os mesmos entre duas listas: CollectionAssert.AreEqual public void TestCollectionAreEqual() List<string> first = new List<string>(); first.add( "a" ); first.add( "b" ); first.add( "c" ); List<string> second = new List<string>(); second.add( "a" ); second.add( "b" ); second.add( "c" ); //second.add( "d" ); //Lista second tem um item a mais -> erro. CollectionAssert.AreEqual( first, second ); 5.2 CollectionAssert.AreNotEqual Oposto de CollectionAssert.AreEqual 5.3 CollectionAssert.AllItemsAreUnique Valida se não existe nenhum valor duplicado em uma lista. Se algum item repetir, o teste falha: CollectionAssert.AllItensAreUnique public void TestCollectionAreUnique() List<string> first = new List<string>(); first.add( "a" ); first.add( "b" ); first.add( "c" ); //first.add( "c" ); //Lista possui dos itens C -> erro. CollectionAssert.AllItemsAreUnique( first ); 5.4 CollectionAssert.Contains Valida se lista contém determinado item CollectionAssert.Contains Confidencial DBServer, 2016 Página 23 de 34

public void TestCollectionAssertContains() List<string> first = new List<string>(); first.add( "a" ); first.add( "b" ); first.add( "c" ); CollectionAssert.Contains( first, "b" ); //CollectionAssert.Contains( first, "x" ); //Lista não contém x -> erro. 5.5 CollectionAssert.DoesNotContain Oposto de CollectionAssert.Contains 5.6 CollectionAssert.ReferenceEquals Valida se itens estão referenciando a mesma classe: CollectionAssert.ReferenceEquals public void TestCollectionReferencingSameClass() List<string> lst1 = new List<string>(); List<string> lst2 = new List<string>(); CollectionAssert.ReferenceEquals( lst1, lst2 ); 5.7 CollectionAssert.AllItemsAreNotNull Valida se todos os itens não são nulos: CollectionAssert.AllItemsAreNotNull public void TestCollectonAllItensAreNotNull() List<string> lst1 = new List<string>(); //lst1.add( null ); //Valor nulo -> erro. lst1.add( "a" ); lst1.add( "b" ); CollectionAssert.AllItemsAreNotNull( lst1 ); 5.8 CollectionAssert.AllItemsAreInstancesOfType Valida se todos itens da lista são de determinado tipo: Confidencial DBServer, 2016 Página 24 de 34

CollectionAssert.AllItemsAreInstanceOfType public void TestCollectionAllItemsAreInstancesOfType() List<object> lst1 = new List<object>(); lst1.add( "a" ); lst1.add( "b" ); //lst1.add( 1 ); //Item não é string -> erro. CollectionAssert.AllItemsAreInstancesOfType( lst1, typeof( string ) ); 5.9 CollectionAssert.IsSubsetOf Valida se um conjunto de itens pertence a outra lista CollectionAssert.IsSubsetOf public void TestCollectionIsSubset() List<string> lst1 = new List<string>(); lst1.add( "a" ); lst1.add( "b" ); lst1.add( "c" ); lst1.add( "d" ); List<string> lst2 = new List<string>(); lst2.add( "a" ); lst2.add( "b" ); //lst2.add( "e" ); //Item 'e' não pertence a lst1 -> erro. CollectionAssert.IsSubsetOf( lst2, lst1 ); 5.10 CollectionAssert.IsNotSubsetOf Oposto de CollectionAssert.IsSubsetOf Confidencial DBServer, 2016 Página 25 de 34

6. ExpectedException É possível indicarmos para nosso teste que queremos receber uma excessão como resultado do teste e faze-lo passar quando receber esta excessão. Retornando ao nosso exemplo anterior, criei a classe Calculadora e dentro dela o método Dividir, que divide dois valores e retorna um resultado. Porém, inclui neste método uma validação para retornar uma excessão do tipo DividedByZeroException quando o divisor for igual a zero. Nossa classe calculadora: Calculadora public class Calculadora : ICalculadora public double Dividir(double dividendo, double divisor) if ( divisor == 0 ) throw new DivideByZeroException(); return dividendo / divisor; Nosso teste: DeveRetornarException /// <summary> /// Valida se retornou exception /// </summary> [ExpectedException(typeof(DivideByZeroException))] public void DeveRetornarException() ICalculadora calculadora = new Calculadora(); double result = calculadora.dividir( 10, 0 ); Assert.AreEqual( 0, result ); Perceba que abaixo do atributo foi incluído o atributo [ExpectedException(typeof(DivideByZeroException))], que indica que nosso método tem que receber essa excessão como retorno do teste. Com isso, o teste passará ao receber esta excessão. Confidencial DBServer, 2016 Página 26 de 34

7. Nunit Framework A idéia desta sessão é demostrar que também é possível utilizar um framework de testes diferente da solução nativa oferecida pelo Visual Studio, apresentando a instalação e realização dos mesmos testes feitos anteriormente utilizando o Nunit framework. 7.1 Vantagens do Nunit Framework A solução de testes do Visual Studio e o Nunit são muito semelhantes, mas podemos citar algumas vantagens do Nunit: Nunit tem uma interface gráfica própria onde basta associar a dll que deseja testar e realizar o teste, permitindo que mais usuários possam realizar o teste sem a necessidade de possuir o Visual Studio instalado. Nunit tem atualizações mais constantes que o VisualStudio. Nunit tem uma apresentação mais detalhada das excessões encontradas nos testes. Nunit tem opções de Asserts. 7.2 Instalação e configuração Crie um novo projeto do tipo ClassLibrary. Eu nomeei meu projeto como TDD.NunitTest. Adicione referencia ao projeto TDD.Model. Acesse a url http://nunit.org/?p=download e faça o download e a instalação do Nunit. Neste tutorial estou utilizando a versão 2.6.4. Confidencial DBServer, 2016 Página 27 de 34

Obs: Tive problemas instalando a versão 3.0.1, tive que desinstalar e instalar a 2.6.4 para conseguir rodar. Caso o mesmo ocorra com você, é necessário instalar o Nunit via Package Manager Console ao invés do Nuget Package, pois precisamos da versão 2.6.4 que é anterior. Caso o erro não ocorra, o Nunit pode ser baixado normalmente pelo Manage Nuget Packages. Instalação via Nuget: No projeto de teste (no meu caso TDD.NunitTest), clique com o botão direito e então Manage Nuget Packages: Selecione Browse, pesquise por Nunit e então clique no botão Install, no canto superior direito: Instalação pelo Package Console: Confidencial DBServer, 2016 Página 28 de 34

Na janela que abrir, digite o comando abaixo para instalar a versão 2.6.4 do Nunit: Confidencial DBServer, 2016 Página 29 de 34

Após finalizar a instação, podemos ver a referência adicionada ao nosso projeto: 7.3 Executando testes no Nunit Nunit instalado, podemos codificar nosso teste. Crie uma classe no projeto TDD.NunitTest e adicione o código abaixo. Estes são os mesmos métodos utilizados anteriormente, porém adaptados para serem usados pelo Nunit, utilizando os atributos [TestFixture] ao invés de [TestClass] e [Test] ao invés de. Note também que possuimos dois métodos a mais aqui, decorados com os atributos [TestFixtureSetUp] e [TestFixtureTearDown]. O método decorado com [TestFixtureSetUp] sempre roda antes dos demais testes toda vez que qualquer teste da mesma classe é executado. Ele e é utilizado para inicializar configurações necessárias para o processo como um todo, como inicializar strings de conexões, por exemplo. O método decorado com [TestFixtureTearDown] sempre roda após os demais testes e é utilizado para finalizar objetos, fechar conexões, etc. Rode o teste da mesma forma anterior. CarroTest com Nunit Confidencial DBServer, 2016 Página 30 de 34

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NUnit.Framework; using TDD.Domain; namespace TDD.NunitTest [TestFixture] public class CarroTest private IMotor motor = null; private ILataria lataria = null; /// <summary> /// Este método sempre será executado ANTES dos testes /// </summary> [TestFixtureSetUp] public void StartTest() motor = new Motor(); lataria = new Lataria(); /// <summary> /// Este método sempre será executado APOS a execução dos testes /// </summary> [TestFixtureTearDown] public void EndTest() motor = null; lataria = null; /// <summary> /// Valida se atributo Motor da classe Carro não é nulo /// </summary> [Test] public void DevePossuirMotor() //IMotor motor = new Motor(); //ILataria lataria = new Lataria(); ICarro carro = new Carro( motor, lataria ); Assert.IsNotNull( carro.motor, "Motor é nulo 0 1!", "[X]", "[Y]" ); /// <summary> /// Valida se carro possui 4 rodas /// </summary> [Test] public void DevePossuirQuatroRodas() Confidencial DBServer, 2016 Página 31 de 34

//IMotor motor = new MotorY(); //ILataria lataria = new Lataria(); ICarro carro = new Carro( motor, lataria ); List<IRoda> rodas = carro.rodas; Assert.AreEqual( 4, rodas.count ); /// <summary> /// Valida se carro possui 2 portas /// </summary> [Test] public void DevePossuirDuasPortas() //IMotor motor = new Motor(); //ILataria lataria = new Lataria(); ICarro carro = new Carro( motor, lataria ); List<IPorta> portas = carro.portas; Assert.AreEqual( 2, portas.count ); Outra forma de utilizar o Nunit é usando o Nunit Application, que foi instalado anteriormente. Ele pode ser encontrado em All Programs: Ao abrir o programa, vá em File / Open Project e selecione a dll do nosso projeto TDD.NunitTest. O Nunit ira carregar todos nossos métodos de teste: Confidencial DBServer, 2016 Página 32 de 34

Clique em Run e ele executará todos os testes. Confidencial DBServer, 2016 Página 33 de 34

8. Fontes http://tableless.com.br/tdd-por-que-usar/ http://www.gonow.com.br/blog/2011/07/31/tech-talk-gonow-debate-pros-e-contras-do-tdd-e-do-bdd/ https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assert.aspx http://www.c-sharpcorner.com/uploadfile/dacca2/fundamental-of-unit-testing-understand-mock-object-inunit/ https://www.visualstudio.com/en-us/get-started/code/create-and-run-unit-tests-vs Histórico da Revisão Data Descrição Responsável 23/02/2016 Criação do arquivo Wagner De Rossi Confidencial DBServer, 2016 Página 34 de 34