Pesquisa de site

Como eu construo e expando o desenvolvimento e testes de aplicativos


Comece o desenvolvimento de forma simples, escrevendo e testando seu código com Um elemento e depois expanda-o para Muitos.

No meu artigo anterior, expliquei por que resolver problemas de codificação de uma só vez, como se fossem hordas de zumbis, é um erro. Também expliquei o primeiro princípio do ZOMBIES, Zero. Neste artigo, demonstrarei os próximos dois princípios: Um e Muitos.

ZOMBIES é uma sigla que significa:

Z – Zero

O – Um

M – Muitos (ou mais complexos)

B – Comportamentos limite

I – Definição de interface

E – Exerça um comportamento excepcional

S – Cenários simples, soluções simples

No artigo anterior, você implementou Zero, que fornece o caminho mais simples possível através do seu código. Não há absolutamente nenhuma lógica de processamento condicional em qualquer lugar. Agora é hora de você passar para o One.

Ao contrário do Zero, que basicamente significa que nada é adicionado, ou temos um caso vazio, nada para cuidar, One significa que temos um único caso para cuidar de. Esse único caso pode ser um item da coleção, ou um visitante, ou um evento que exija tratamento especial.

Com muitos, estamos agora lidando com casos potencialmente mais complicados. Dois ou mais itens da coleção, dois ou mais eventos que exigem tratamento especial e assim por diante.

Um em ação

Aproveite o código do artigo anterior adicionando algo ao seu carrinho de compras virtual. Primeiro, escreva um teste falso:

[Fact]
public void Add1ItemBasketHas1Item() {
	var expectedNoOfItems = 1;
	var actualNoOfItems = 0;
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

Como esperado, este teste falha porque você codificou um valor incorreto:

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.NewlyCreatedBasketHas0Items [FAIL]
  X tests.UnitTest1.NewlyCreatedBasketHas0Items [4ms]
  Error Message:
   Assert.Equal() Failure
Expected: 0
Actual: 1 
[...]

Agora é a hora de pensar em como parar de fingir. Você já criou uma implementação de um carrinho de compras (um ArrayList para armazenar itens). Mas como você implementa um item?

A simplicidade deve ser sempre o seu princípio orientador, e não sabendo muito sobre o item em si, você pode fingir um pouco implementando-o como outra coleção. O que essa coleção poderia conter? Bem, como você está mais interessado em calcular os totais da cesta, a coleção de itens deve, no mínimo, conter um preço (em qualquer moeda, mas para simplificar, use dólares).

Uma coleção simples pode conter um ID de um item (um ponteiro para o item, que pode ser mantido em outro lugar no sistema) e o preço associado de um item.

Uma boa estrutura de dados que pode capturar isso facilmente é uma estrutura de chave/valor. Em C#, a primeira coisa que vem à mente é Hashtable.

No código do aplicativo, adicione um novo recurso à interface IShoppingAPI:

int AddItem(Hashtable item);

Esse novo recurso aceita um item (uma instância de uma Hashtable) e retorna o número de itens encontrados no carrinho de compras.

Nos seus testes, substitua o valor codificado por uma chamada para a interface:

[Fact]
public void Add1ItemBasketHas1Item() {            
    var expectedNoOfItems = 1;
    Hashtable item = new Hashtable();
    var actualNoOfItems = shoppingAPI.AddItem(item);
    Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

Este código instancia Hashtable e o nomeia como item, depois invoca AddItem(item) na interface de compras, que retorna o número real de itens no cesta.

Para implementá-lo, consulte a classe ShoppingAPI:

public int AddItem(Hashtable item) {
    return 0;
}

Você está fingindo de novo só para ver os resultados dos seus testes (que são os primeiros clientes do seu código). Caso o teste falhe (conforme esperado), substitua os valores codificados pelo código real:

public int AddItem(Hashtable item) {
    basket.Add(item);
    return basket.Count;
}

No código de trabalho, adicione um item à cesta e retorne a contagem dos itens na cesta:

Test Run Successful.
Total tests: 2
     Passed: 2
 Total time: 1.0633 Seconds

Então agora você passou em dois testes e praticamente cobriu Z e O, as duas primeiras partes de ZOMBIES.

Um momento de reflexão

Se você olhar para o que fez até agora, perceberá que, ao concentrar sua atenção em lidar com os cenários Zero e One mais simples possíveis, você terá consegui criar uma interface e também definir alguns limites lógicos de processamento! Não é incrível? Agora você tem as abstrações mais importantes parcialmente implementadas e sabe como processar casos em que nada é adicionado e quando algo é adicionado. E como você está construindo uma API de e-commerce, certamente não prevê colocar quaisquer outros limites que limitariam seus clientes na hora de fazer compras. O seu carrinho de compras virtual é, para todos os efeitos, ilimitado.

Outro aspecto importante (embora não necessariamente imediatamente óbvio) do refinamento gradual que ZOMBIES oferece é a relutância em saltar de cabeça nas dificuldades da implementação. Você deve ter notado como isso é tímido em relação à implementação de qualquer coisa. Para começar, é melhor falsificar a implementação codificando os valores. Somente depois de ver que a interface interage com seu teste de maneira sensata você estará disposto a arregaçar as mangas e fortalecer o código de implementação.

Mas mesmo assim, você deve sempre preferir construções simples e diretas. E esforce-se para evitar a lógica condicional tanto quanto possível.

Muitos em ação

Expanda seu aplicativo definindo suas expectativas quando um cliente adiciona dois itens à cesta. O primeiro teste é falso. Ele espera 2, mas força-o a falhar codificando 0 itens:

[Fact]
public void Add2ItemsBasketHas2Items() {
	var expectedNoOfItems = 2;
	var actualNoOfItems = 0;
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

Quando você executa o teste, dois deles passam com sucesso (os dois anteriores, os testes Z e O), mas como esperado, o teste codificado falha:

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.Add2ItemsBasketHas2Items [FAIL]
  X tests.UnitTest1.Add2ItemsBasketHas2Items [2ms]
  Error Message:
   Assert.Equal() Failure
Expected: 2
Actual: 0

Test Run Failed.
Tatal tests: 3
     Passed: 2
     Failed: 1

Substitua os valores codificados pela chamada para o código do aplicativo:

[Fact]
public void Add2ItemsBasketHas2Items() {
	var expectedNoOfItems = 2;
	Hashtable item = new Hashtable();
	shoppingAPI.AddItem(item);
	var actualNoOfItems = shoppingAPI.AddItem(item);
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

No teste, você adiciona dois itens (na verdade, você está adicionando o mesmo item duas vezes) e então compara o número esperado de itens com o número de itens da instância shoppingAPI após adicionar o item no segundo tempo.

Todos os testes agora passam!

Fique atento

Agora você completou a primeira passagem da parte ZOM da equação. Você passou em Zero, em One e em Many. No próximo artigo, darei uma olhada em B e I. Fique atento!

Artigos relacionados: