Implementando testes de unidade em uma empresa que não faz isso

19

O chefe de desenvolvimento de software da minha empresa acabou de "renunciar" (ou seja, demitido) e agora estamos procurando melhorar as práticas de desenvolvimento em nossa empresa. Queremos implementar testes de unidade em todos os softwares criados daqui em diante.

O feedback dos desenvolvedores é este:

  • Sabemos que o teste é valioso
  • Mas você está sempre mudando as especificações para que seja uma perda de tempo
  • E seus prazos são tão apertados que não temos tempo suficiente para testar de qualquer maneira

O feedback do CEO é o seguinte:

  • Gostaria que nossa empresa tivesse testes automatizados, mas não sei como fazer isso acontecer
  • Não temos tempo para escrever grandes documentos de especificação

Como os desenvolvedores conseguem as especificações agora? Palavra de boca ou slide do PowerPoint. Obviamente, isso é um grande problema. Minha sugestão é esta:

  • Vamos também fornecer aos desenvolvedores um conjunto de dados de teste e testes de unidade
  • Essa é a especificação. Cabe à gerência ser clara e quantitativa sobre o que deseja.
  • Os desenvolvedores podem colocar qualquer outra funcionalidade que considerem necessária e não precisa ser coberta por testes

Bem, se você já esteve em uma empresa que estava nessa situação, como resolveu o problema? Essa abordagem parece razoável?

Suporte para PeteMonica
fonte
1
Parece uma causa perdida para mim. Os testes de unidade provam que você está em conformidade com as especificações, mas está constantemente mudando de acordo com os desenvolvedores (portanto, não é realmente uma especificação, mas mais uma lista de desejos) e seu CEO não tem noção.
James
@ James - Os negócios precisam mudar, tanto quanto qualquer coisa que a engenharia de software tenha sobre o gerenciamento dessa mudança. Para mim, o que o CEO disse é perfeitamente razoável.
Mark Booth
@ MarkBooth Há mudanças e há um estado constante de fluxo. Releia a pergunta. Esta empresa está inventando isso.
James
@ James Você está fazendo um julgamento de valor sem qualquer base real. Só porque os desenvolvedores reclamam não significa que a empresa está inventando tudo à medida que avança . Alguns de nós não trabalham em ambientes programados e facilmente especificados. Eu tenho novos usuários a cada semana, e todos desejam fazer algo um pouco diferente dos usuários anteriores. Eles frequentemente descobrem, no meio do tempo alocado, que o software não faz o que precisa. Talvez eu não goste de ser chamado no sábado para implementar algo que eles nunca sabiam que precisavam, mas isso geralmente faz parte do trabalho em um local ágil.
Mark Booth

Respostas:

17

Parece que você está misturando dois tipos diferentes de testes: testes de unidade e testes de sistema / aceitação . Os primeiros operam em um nível inferior, testando pequenos trechos de código (geralmente métodos individuais), que geralmente residem nas profundezas do programa, não diretamente visíveis aos usuários. O último testa todo o programa como visto por seus usuários, em um nível muito maior de granularidade. Assim, apenas o último pode ser baseado em qualquer forma de especificação do sistema.

A separação dos dois problemas facilita a mudança para um processo de desenvolvimento aprimorado. Comece a escrever testes de unidade o mais rápido possível , independentemente de como o software é (não) especificado em alto nível. Sempre que um desenvolvedor cria ou altera um método, ele faz algo concreto, que pode (e deve) ser testado por unidade. Na minha experiência, mesmo a alteração de requisitos de alto nível normalmente não afeta drasticamente esses blocos de código de nível inferior: o código geralmente precisa ser reorganizado, em vez de descartado ou reescrito completamente. Consequentemente, a maioria dos testes de unidade existentes continuará funcionando bem.

Uma condição importante para permitir o teste de unidade é: os prazos não devem ser decididos pela gerência antecipadamente, mas devem basear-se em estimativas de trabalho dos desenvolvedores (que, por sua vez, devem incluir em suas estimativas o tempo necessário para escrever testes de unidade adequados). Ou, se o prazo for fixado, o escopo da entrega deve ser negociável. Nenhuma quantidade de (mis) gerenciamento pode alterar a verdade fundamental de que um determinado número de desenvolvedores só pode fornecer uma certa quantidade de trabalho de qualidade em um determinado período de tempo.

Paralelamente, comece a discutir a melhor maneira de esclarecer e documentar os requisitos e transformá-los em testes de aceitação de alto nível. Esse é um processo mais longo de refinamento sucessivo, que pode facilmente levar anos para chegar a um estado melhor e estável em toda a organização. Uma coisa parece bastante certa em sua descrição: tentar corrigir requisitos em constante mudança, escrevendo grandes documentos de especificação antecipadamente, simplesmente não vai funcionar . Em vez disso, recomenda-se avançar para uma abordagem mais ágil, com lançamentos e demonstrações frequentes de software para os usuários, e muitas discussões sobre o que eles realmente desejam. O usuário tem o direito de mudar de idéia sobre os requisitos a qualquer momento - no entanto, cada alteração tem seu custo (em tempo e dinheiro). Os desenvolvedores podem estimar o custo de cada solicitação de mudança, o que, por sua vez, permite que o usuário / proprietário do produto tome decisões informadas. "Certamente, essa alteração de recurso seria legal ... mas se atrasar o lançamento desse outro recurso crucial e custar tanto, vamos colocá-lo em atraso por enquanto".

Fazer com que os usuários definam casos de teste de aceitação e criem dados de teste é uma ótima maneira de envolvê-los mais e criar confiança mútua entre usuários e desenvolvedores. Isso força as duas partes a se concentrarem em critérios de aceitação concretos, mensuráveis ​​e testáveis ​​e a pensar nos casos de uso com muito mais detalhes do que o típico. Como resultado, os usuários podem verificar o status atual do desenvolvimento em primeira mão a cada versão, e os desenvolvedores recebem feedback de medição mais concreto e tangível sobre o status do projeto. Observe, porém, que isso requer maior comprometimento dos usuários e novas formas de operação, que podem ser difíceis de aceitar e aprender.

Péter Török
fonte
1
E a razão do voto negativo é ...?
Péter Török
1
+1 por "avançar para uma abordagem mais ágil", lembra-me "Andar sobre a água e desenvolver software a partir de uma especificação são fáceis se ambos estiverem congelados". - Edward V Berard
Mark Booth
@ Peter Torok Obrigado ... você tem algum link para informações relevantes sobre testes de aceitação?
usar o seguinte
@Pete, é difícil ser mais específico sem saber mais sobre seus projetos, tipos de aplicativos, etc. A pesquisa rápida mostra alguns links promissores.
Péter Török
8

Minha experiência em fazer a transição

Por muitos anos, fiquei com a má compreensão de que não tinha tempo suficiente para escrever testes de unidade para o meu código. Quando escrevi testes, eles estavam inchados, coisas pesadas que só me incentivaram a pensar que só deveria escrever testes de unidade quando soubesse que eram necessários.

Recentemente, fui encorajado a usar o Test Driven Development e achei uma revelação completa. Agora estou firmemente convencido de que não tenho tempo para não escrever testes de unidade .

Na minha experiência, desenvolvendo com testes em mente, você acaba com interfaces mais limpas, classes e módulos mais focados e, geralmente, mais código SOLID testável.

Toda vez que trabalho com código legado que não possui testes de unidade e preciso testar manualmente algo, fico pensando "isso seria muito mais rápido se esse código já tivesse testes de unidade". Toda vez que tenho que tentar adicionar a funcionalidade de teste de unidade ao código com alto acoplamento, fico pensando "isso seria muito mais fácil se tivesse sido escrito de maneira desacoplada".

Comparando e contrastando as duas estações experimentais que eu apoio. Um já existe há algum tempo e possui uma grande quantidade de código legado, enquanto o outro é relativamente novo.

Ao adicionar funcionalidade ao laboratório antigo, geralmente é necessário ir ao laboratório e passar muitas horas trabalhando com as implicações da funcionalidade de que eles precisam e como posso adicionar essa funcionalidade sem afetar nenhuma outra funcionalidade. O código simplesmente não está configurado para permitir testes off-line, então praticamente tudo precisa ser desenvolvido on-line. Se eu tentasse me desenvolver off-line, acabaria com mais objetos simulados do que seria razoável.

No laboratório mais recente, geralmente posso adicionar funcionalidades desenvolvendo-as off-line na minha mesa, zombando apenas daquilo que é imediatamente necessário e depois passando um curto período de tempo no laboratório, resolvendo os problemas restantes que não foram detectados. -linha.

Meu conselho

Parece que você começou bem, sempre que fizer grandes alterações no seu fluxo de trabalho de desenvolvimento, você precisa garantir que todos estejam envolvidos na tomada dessa decisão e, idealmente, que a maioria das pessoas tenha adquirido. Da sua pergunta, parece que você acertou. Se as pessoas não têm entusiasmo pela idéia, está fadado a falhar ou gerar má vontade.

A menos que você possa apresentar um caso de negócios atraente, eu não recomendaria uma implementação inicial de testes e especificações de unidade para todo o sistema. Como mencionei acima, se um sistema não for projetado com testes em mente, pode ser muito difícil escrever testes automatizados para ele.

Em vez disso, eu recomendaria começar pequeno e usar a regra dos escoteiros :

Sempre deixe o acampamento mais limpo do que o encontrado.

Se enquanto você estiver implementando algo nessa base de código, poderá identificar os testes específicos necessários para testar o comportamento existente e fazer a transição do comportamento antigo para o novo, então você documentou a alteração nas especificações e começou a implementar testes de unidades para Seu sistema.

Os módulos nos quais você não toca não são submetidos a testes de unidade, mas se você não os estiver tocando, provavelmente é porque eles já foram exaustivamente testados em uso e não precisam de alterações, ou nunca são usados.

O que você deseja evitar é desperdiçar toda uma carga de esforço do desenvolvedor escrevendo testes que nunca serão necessários (o YAGNI funciona tão bem para o código de teste quanto para o código de produção * 8 '), nunca mais será usado e desmoralizará as pessoas. pensando que os testes são inúteis, afinal.

Sumário

Comece pequeno, construa confiança nos testes de forma incremental e obtenha valor comercial desenvolvendo testes quando e onde eles mais beneficiam sua equipe.

Mark Booth
fonte
2

A primeira coisa a fazer é se concentrar não nos testes, mas em acertar o processo geral. Não adianta testar nada se você não entender completamente o que ele deve fazer!

Então .. especificações primeiro e especificações documentadas que não são alteradas (bem, não imediatamente). Você deve procurar fazer isso. Eu recomendo um site em que os usuários possam fazer upload das especificações ou digitá-las diretamente. Você também pode vincular isso a um rastreador de erros e a um guia sobre o andamento do projeto.

As chances são de que isso é tudo o que você realmente precisa. Você pode adicionar testes de unidade internamente e o gerenciamento nunca precisa saber que os desenvolvedores estão fazendo testes de unidade. De certa forma, é assim que deveria ser.

Você ainda precisará fazer o teste do sistema, mas isso também pode ser vinculado ao site de gerenciamento do projeto, uma vez lançado, a equipe de teste (mesmo que seja outro desenvolvedor sortudo em rotação) pode atualizá-lo com testes que eles usaram para ver se a coisa toda fica junto.

Sinceramente, acho que isso não vai mudar da noite para o dia, se você estiver acostumado a obter especificações de 'boca a boca', então a batalha quase mudará completamente esse comportamento - e você terá resistência a isso. Um usuário (ou BA ou PM ou qualquer pessoa) que está acostumado a dizer "apenas faça x" e agora precisa anotar tudo isso não vai responder bem, é provável que ele escreva documentos de especificações vagas e depois os esclareça com atualizações boca a boca. Portanto, esqueça os testes de unidade e comece o grande problema que você tem com o ciclo de vida do desenvolvimento.

gbjbaanb
fonte
1

Primeira questão: para "fornecer aos desenvolvedores um conjunto de dados e testes de unidade", você deve primeiro escrever esses testes de unidade, que é um trabalho dos desenvolvedores. Os testes de unidade também não substituem a especificação: a especificação deve ter um nível de abstração mais alto que os testes de unidade.

Segunda questão: parece que você deseja a cobertura máxima do teste de unidade. Nesse caso, sim, custará muito tempo e dinheiro para escrever testes e códigos em um contexto em que os requisitos mudam constantemente. Em vez disso, decida quais partes do código são críticas e teste a unidade apenas essas partes. Em muitos casos, os requisitos que mudam não afetam as partes críticas do produto. Um cliente (ou CEO, ou qualquer outro) geralmente pede para mover este painel para a direita ou alterar a cor deste título de vermelho para verde: coisas com as quais ninguém se importa e que não exige testes intensivos. Por outro lado, um cliente nunca pedirá para alterar o algoritmo de hash de SHA512 para SHA256 ou para alterar a maneira como você armazena sessões, enquanto essas são as partes que exigirão mais testes.

Arseni Mourzenko
fonte