TDD – Desenvolvimento Orientado a Testes com Delphi

TDD – Desenvolvimento Orientado a Testes (Test Driven Development) é uma técnica de desenvolvimento de software relacionado aos conceitos de XP (Programação Extrema). que baseia em um ciclo curto de repetições.

O ciclo de desenvolvimento com TDD se resume em:

1 – Primeiro crie os testes unitários. 

2 – Crie o código até que os testes funcionem.

3 – Refatore o código. 

TDD é uma das formas de manter seu código funcionando seguramente mesmo que sejam feitas mudanças radicais no projeto. O primeiro passo, onde é requisito escrever um teste antes de ter o código final desenvolvido no projeto, certamente é o ponto mais difícil de entendimento entre profissionais e equipes que ainda não conhecem esta técnica.

O fato é que nesta primeira etapa é justamente onde você vai entender dentre muitas outras coisas, que terá uma regra seguramente funcionando antes de partir para o desenvolvimento do código.

Como assim? Você está me dizendo que “do nada” eu tenho que codificar uma regra?

Você ainda pode estar se perguntando: “Se eu ainda não tenho o código que funciona, como terei um teste para ele?”

Eu lhe digo, justamente! A regra no caso do TDD é justamente ter um teste que ainda não funcione, para que você passe para a segunda etapa que é “Criar um código que faça seu teste funcionar”, certo?

Para que isto se torne possível, neste texto irei falar do uso do framework DUnitX.

DUnitX é um framework open-source que pode ser utilizado no Delphi a partir da versão 2010. Ele é baseado em frameworks como NUnit e xUnit, contendo inúmeros métodos para implementação de testes unitários de suas classes e métodos. DUnitX utiliza métodos anônimos e generics. Existem muitos artigos e videos com exemplos práticos a serem explorados, a princípio você pode conhecer um pouco mais sobre este framework, conceitos e métodos a serem utilizados em: http://docwiki.embarcadero.com/RADStud…/…/en/DUnitX_Overview

Ok, mas voltando ao texto,  isso pode não está bem claro ainda, então vamos ao tal código do teste.

Antes quero lhe dizer que cada teste, deve ser baseado em uma regra compreendida pela análise do problema a ser resolvido, então vamos ver um exemplo comum para iniciar.

Caso do teste:

Ao iniciar uma venda, em seguida finalizar a mesma venda sem itens lançados,  o sistema deverá informar o usuário por diálogo de exceção, com a seguinte mensagem “É necessário pelo menos um item lançado para finalizar a venda”.

Observe a estrutura das classes de Venda. Note que não existem implementações desta regra de negócio na classe TVenda.

ClasseBase

Mas isto não impede a criação dos métodos de teste, pois é justamente o que deve ser feito quando se trabalha com TDD, Desenvolvimento Orientado a Testes!

Agora vamos ver como é feito o Teste:

VendaTest

E o que este teste quer dizer mesmo?

Simples! Vamos ver cada parte demonstrada por cores.

Verde: Este método Setup serve para que seja executado algo para cada método de teste, isto ajuda para que você separe a parte de inicialização de variáveis e instancias de objetos e deixe seu código somente com a regra a ser testada.

Vermelho: É outro método a ser executado, desta vez após todo método de teste que for implementado. Assim como o Setup, neste método, você pode liberar possíveis objetos da memória e até executar outros procedimentos como finalizar uma conexão por exemplo.

Amarelo: Este é o primeiro método de teste conforme nosso caso relatado acima!

E como foi implementado este teste?

No framework de testes DUnitX,  existe a classe Assert que contém inúmeros métodos para que possa ser feito várias condições, para nosso caso, foi utilizado o método  WillRaiseWithMessage (a grosso modo quer dizer: Irá(deverá) levantar uma exceção contendo a seguinte mensagem). Para este método, podem ser passados os seguintes parâmetros:

1 – Um procedimento anônimo com uma implementação que deverá ser a mesma utilizada no sistema, ou seja, Inicia uma venda e Finaliza uma venda, neste caso sem lançar nenhum item, assim como previsto no Caso de teste.

2 – Uma classe de exceção, pode ser nil caso não tiver nenhuma específica.

3 – A mensagem que será esperada pelo sistema ao ocorrer o caso  do teste. Esta mensagem tem que ser exatamente a mesma, caso contrário o teste irá falhar.

Pronto! Assim concluímos a primeira etapa do teste, este teste já pode ser executado e deverá dar errado, é isso que precisamos fazer até o momento.

Olhe o resultado ao executar o teste:

ErroTeste

Pode comemorar, o teste falhou!

Veja só o que temos, o retorno de que o teste FinalizarVendaSemItensLancados não retornou um exceção como esperado!

Agora sim já podemos partir para o segundo passo que é justamente fazer isto acontecer em nossa classe, consequentemente na aplicação onde ela será utilizada.

O que precisamos fazer é simplesmente codificar nossa classe para que dispare uma exceção com a mensagem esperada pelo teste, então observe um exemplo de como isto pode ser feito na classe TVenda:

ImplementacaoTeste

Assim, ao chamar o método Finalizar, será verificado se existem itens lançados, caso não existam é disparado a exceção com a mensagem correspondente.

Então ao executar novamente a aplicação de testes, devemos receber o seguinte resultado.

TestePassou

A partir deste modelo, você já pode criar outros testes unitários para sua classe, não há limites para isto, o ideal é que sejam atendidos 100% dos possíveis casos de sua aplicação, quanto mais casos forem atendidos melhor!

Bom, isto está longe de ser um material completo sobre testes unitários, porém já é o suficiente para que você conheça como irá finalmente garantir que sua aplicação se torne segura independente da mudança sofrida durante a vida do projeto

Para finalizar quero ressaltar alguns benefícios ao adotar TDD:

  • Certeza de que se algum outro desenvolvedor acidentalmente mudar a regra de negócio na aplicação, o teste irá falhar antes que chegue ao cliente.
  • Conhecimento de todas as regras de negócio ao ler os casos de testes.
  • Identificar rapidamente regras incorretas ou obsoletas.
  • Facilidade de alocação de um novo profissional para o projeto sem maiores riscos de mexer em código que já estava funcionando.
  • Identificar quais são os mínimos e máximos argumentos para que regras de negócio sejam atendidas (eliminando redundância e métodos desnecessários).
  • Documentação de regras de negócio, baseada nos casos de testes.
  • Confiança!

É isso ai, muito obrigado por ler este artigo e não para por aqui, estou editando alguns videos onde certamente falarei mais sobre testes :d

Obrigado.

Carlos Eduardo – Delphi Clean Code

 

Técnicas de Refatoração com Delphi

casa

Imagem retirada de: http://www.desenvolvimentoagil.com.br/xp/praticas/refatoracao

Olá

Uma das técnicas que quando utilizadas fazem muita diferença  na vida de um projeto é a Refatoração.

O que é refatorar?

Refatorar é alterar a estrutura do código sem alterar o seu comportamento.

Um dos grandes nomes da técnica de refactoring – refatoração –  é Martin Fowler. Seu livro mais importante sobre refatoração é Refactoring: Improving the Design of Existing Code (ISBN 0-201-48567-2), onde são explicados os conceitos, motivações e uma série de refatorações descritas passo a passo.

Neste você verá um pouco sobre algumas técnicas que podem ser utilizadas para ter bons resultados com a refatoração de código.

Continue Lendo “Técnicas de Refatoração com Delphi”

Qual seu controle de versão?

 

ArtigoControleVersao

 

Assim como a maioria das tecnologias, linguagens, IDE’s etc. Utilizar controle de versão exige muito estudo, análise e testes para uma boa escolha, isto é, adequar a estrutura, os projetos e capacitar equipes para trabalhar com segurança, desempenho, funcionalidades e o mínimo de complexidade.

Então, sugiro mais um questionário para compartilharmos qual ferramenta utilizamos no dia a dia e ainda comentarmos um pouco de nossas experiências boas ou ruins sobre as seguintes opções Git – SVN – Mercurial.

Responda em: Facebook Grupo Delphi Clean Code

Lembrando que o Delphi já possui integraçã
o com os 3 sistemas, sendo:

SVN desde a versão XE,

Git desde a versão XE7,

Mercurial desde a versão XE8.

Participe!

Obrigado,

Carlos – Delphi Clean Code.

Guia de Estilo Para Delphi – Convenção de Nomenclatura

Olá,

Uma boa prática de desenvolvimento é seguir um guia de estilo.

A equipe de desenvolvimento do Delphi baseia-se nas convenções do Object Pascal Style Guide 

Estes padrões são também o que a maioria das equipes de desenvolvimento seguem, por exemplo, veja a seguir alguns padrões de nomenclatura:

 

GuiaEstilo1

No entanto, existem ainda outros padrões para nomeação de variáveis globais e locais, estes por sua vez são muitas vezes particulares de cada equipe. Como diz nosso amigo Tio Bob…

“Todo programador tem suas regras de formatação prediletas, mas se ele for trabalhar em equipe, as regras são dela.” – Uncle Bob

Sendo assim, diante do guia de estilo “padrão”, para as variáveis, o guia de estilo recomenda que: As variáveis locais seguem as mesmas regras de nomeação que nomes de campo, exceto que você omitir o F inicial, uma vez que este não é um campo de um objeto. Além disso, também não podem ser utilizados nomes de palavras reservadas, iniciar com números ou conter outros caracteres especiais não suportados.

Eu particularmente já encontrei muitos padrões inclusive documentados por equipes, onde foram adotados prefixos, convenções etc.

E você, qual é o seu estilo ou da sua equipe?

Adicionei uma enquete no canal do facebook.  para identificarmos quais são os estilos mais comuns utilizados, participe e dê sua opinião!

Obrigado,

Carlos – Delphi Clean Code.

 

 

 

 

 

 

 

 

 

TComboBox com valor dinâmico

Bom dia,

Esta é minha primeira postagem no Blog que de forma simples e rápida gostaria de compartilhar algo que procurei a muito tempo no Delphi e nem sabia que era possível.
Quem nunca pensou… “como seria bacana colocar um valor dinâmico no ComboBox, assim como é possível no PHP por exemplo”.

Realmente é possível, segue abaixo o código:

ExemploComboboxObject

Explicando o código:

Linhas 37, 39: Adicionei 3 valores na tabela a serem preenchidos no ComboBox.

Linha 41:  Método clear para eliminar eventuais valores no combobox a ser preenchido

Linha 46: Atribuído os valores formatados a variável FItem a ser adicionada a seguir.

Linha 47: Utilização do método AddObject passando como primeiro parâmetro FItem e em seguida o CAMPOVALOR como objeto de referencia para o item do ComboBox.

Veja que é possível adicionar um Objeto ao ComboBox, sendo que esse objeto tem um Valor, que é o valor dinâmico recebido pela consulta ao Banco de Dados, e apresenta para a seleção a String CAMPONOME, também retirada do Banco de Dados.

Para buscar o VALOR do objeto no ComboBox use:
Variavel := integer(MeuComboBox.Items.Objects[MeuComboBox.ItemIndex]);

Então é isso pessoal, até a próxima.

Alex R. Schmitt

Convertendo entre TInterfacedObject e JSON

Olá,

Depois do vídeo  Convertendo entre Objeto e JSON com apenas uma linha de código , surgiram algumas dúvidas de como seria a conversão para JSON utilizando a mesma classe TJSON mas não com TObject e sim com TInterfacedObject ou com TObjectList. Para responder estas dúvidas, você verá neste artigo, que é tão simples quanto trabalhar com TObject.

Neste artigo vamos ver como é feito quando se tem um TInterfacedObject.

O código a seguir, corresponde a estrutura resumida de uma interface e em seguida a classe herdando desta interface:

PerfilInterface

Agora a implementação semelhante das conversões de TPefilInt para JSON e de JSON para TPerfilInt.

PerfilInterfaceToJSONTest

 

 

 

1

Basicamente é isso, note que é tão simples quanto converter um TObjeto.

Veja também como fazer estas conversões utilizando um TObjectList (Lista de Objetos) neste artigo: Convertendo entre TObjectList e JSON

Obrigado,

Carlos – Delphi Clean Code.

Convertendo entre TObjectList e JSON

Olá,

Neste artigo complementar ao artigo Convertendo entre TInterfacedObject e JSON, que também foi dúvida apontada no vídeo  Convertendo entre Objeto e JSON com apenas uma linha de código , irei demostrar como converter um TObjectList para JSON e um JSON para um  TObjectList.

Veja no exemplo de código abaixo, a estrutura de uma classe para armazenar todos os objetos TPerfil criados para conversão:

ListaPerfil

Esta implementação é suficiente para criar e manter todos os objetos criados do tipo TPerfil, quando o atributo FLista for destruído, todos os objetos da lista serão também destruídos, isto ocorre pois a classe TObjectList faz isto mediante a propriedade OwnsObjects que por padrão já vem como True.

Dai em diante, basta fazer a implementação conforme exemplo abaixo e finalmente teremos a mesma técnica funcionando com a Lista de Objetos.

Exemplo TObjectList para JSON

ObjectListJSON

Algumas observações sobre TObjectList:

  • Na linha 39, veja que foi necessário somente chamar o construtor da classe TPerfil, que a lista com o tipo genérico TPerfil, já criou a instancia, dispensando assim uma variável para cada instancia no seu código.
  • A Lista do tipo TObjectList, também tem alguns métodos como o Last que irá retornar a última instância do objeto criado. Exitem outros métodos como First, Sort, Insert etc.

E para concluir, veja como converter no sentido inverso, isto é, de JSON para TObjectList.

JSONToObjectList2

Pronto!

Com este artigo, espero que tenha respondido as dúvidas.

Obrigado,

Carlos – Delphi Clean Code.

 

 

 

 

Convertendo entre Objeto e JSON com apenas uma linha de código

Primeiro vídeo do canal Delphi Clean Code.

Sabe aquele monte de código que você utilizava para trabalhar com transporte de dados com JSON? Então, agora não precisa mais! No Delphi existe uma classe TJSON com métodos incrivelmente simples prontinhos para você implementar…

Assista o vídeo

Não esqueça de curtir o vídeo e deixar seu comentário para juntos descobrirmos como facilitar nossas vidas utilizando formas simples com Delphi.

Obrigado

Carlos Delphi Clean Code

ThreadVar

Você conhece a palavra reservada ThreadVar? E para que ela serve?

ThreadVar serve para que ao trabalhar com múltiplas Threads, caso necessite acessar uma variável em comum, as threads irão disputar esta variável e assim causar valores absurdos.
A palavra reservada ThreadVar inicia um conjunto de definições de variáveis que são usados por threads.
Continue Lendo “ThreadVar”