Os testes de unidade são realmente úteis? [fechadas]

98

Acabei de me formar em CS e atualmente trabalho como desenvolvedor .NET Júnior (C #, ASP.NET e formulários da web). Quando eu ainda estava na universidade, o assunto dos testes de unidade era coberto, mas eu nunca vi os benefícios disso. Entendo o que ele deve fazer, a saber, determinar se um bloco de código é ou não adequado para uso. No entanto, eu nunca tive que escrever um teste de unidade antes, nem senti a necessidade.

Como eu já mencionei, geralmente estou desenvolvendo com formulários da Web ASP.NET, e recentemente estive pensando em escrever alguns testes de unidade. Mas eu tenho algumas perguntas sobre isso.

Eu li que o teste de unidade geralmente acontece através da escrita de "zombarias". Embora eu entenda esse conceito, não consigo descobrir como devo escrever zombarias para sites completamente dinâmicos e onde quase tudo depende dos dados provenientes de um banco de dados. Por exemplo: eu uso muitos repetidores que têm eventos ItemDataBound etc. (novamente dependendo dos dados "desconhecidos").

Então, pergunta número 1: escrever testes de unidade para formulários da Web do ASP.NET é algo que é feito com freqüência e se é: como resolver o problema do "ambiente dinâmico"?

Quando estou desenvolvendo, passo por muitas tentativas e erros. Isso não significa que não sei o que estou fazendo, mas quero dizer que geralmente escrevo algum código, bato Ctrl F5e vejo o que acontece. Embora essa abordagem faça o trabalho a maior parte do tempo, às vezes sinto que estou sendo um pouco sem noção (por causa da minha pouca experiência). Às vezes, também perco muito tempo assim.

Então, pergunta número 2: Vocês me aconselham a começar a escrever testes de unidade? Acho que isso pode me ajudar na implementação real, mas, novamente, sinto que isso pode me atrapalhar.

Jane Doe
fonte
1
Eu gostaria de dizer apenas que o outro lado disso é que alguns lugares os exigem como prática. Estou em um local agora que não temos permissão para verificar o código, a menos que seja coberto por testes de unidade. Portanto, é importante ressaltar que, mesmo que você não acredite neles, pode ser necessário fazê-los no futuro. Eu acho que é uma habilidade útil para aprender e ter em seu arsenal. Muitas vezes encontrarei pequenos erros e percalços no meu código ao fazer os testes, quase uma pequena sessão de controle de qualidade com você.
Adam
9
Como exatamente você cobriu o teste de unidade sem escrever nenhum teste de unidade? Essa foi uma dessas escolas de "qualificar você mesmo" ou "criar seu próprio currículo"?
22412 JeffO
4
Os testes de unidade são questionáveis ​​- ótimos para idiomas dinâmicos, menos úteis, quanto mais rigoroso for o seu idioma, mas faça testes. Eles não precisam ser testes de unidade, mas você realmente deve ter testes de integração para executar com o JUnit, esses são muito úteis.
Bill K
13
-1 Desculpe, sou a favor de bons argumentos, mesmo que não concorde, mas isso está errado. Ninguém afirma que "os testes de unidade são para detectar bugs no novo código", então esse é um problema - os testes de unidade são para detectar regressões . E a citação de Dijkstra é retirada de contexto - o contexto é que o teste é inútil se você tiver uma especificação formal do seu problema .
sleske
9
"testes de unidade são para capturar regressões". Não. Os testes automatizados são para capturar regressões. As regressões sempre exigem que os mesmos testes sejam executados muitas centenas de vezes, portanto vale a pena o esforço para automatizá-los. Infelizmente, muitas das respostas e comentários sobre esta questão estão realmente lidando com o problema "Os testes automatizados são úteis?". Os testes de unidade podem ser uma forma de teste automatizado, mas eles têm um foco completamente diferente. Certamente considero que os testes automatizados valem seu peso em ouro, mas isso não deve ser usado como argumento para justificar os testes de unidade (ou TDD).
Njr101

Respostas:

124

Na minha opinião: sim, são e sim, você deveria.

  1. Eles dão a você confiança nas alterações que você faz (todo o resto ainda está funcionando). Essa confiança é o que você precisa para moldar o código; caso contrário, você pode ter medo de mudar as coisas.

  2. Eles tornam seu código melhor; os erros mais simples são detectados cedo nos testes de unidade. Capturar bugs cedo e corrigi-los é sempre mais barato do que corrigi-los mais tarde, por exemplo, quando o aplicativo está em produção.

  3. Eles servem como documentação para outros desenvolvedores sobre como seu código funciona e como usá-lo.

O primeiro problema que você enfrenta é que o ASP.NET, por si só, não ajuda a escrever testes de unidade - na verdade, funciona contra você. Se você tiver alguma escolha, comece a usar o ASP.NET MVC , que foi criado com o teste de unidade em mente. Se você não pode usar o ASP.NET MVC, deve usar o padrão MVP no ASP.NET para que pelo menos possa testar sua lógica com facilidade.

Além disso, você só precisa ter proficiência em escrever testes de unidade. Se você pratica TDD, seu código é criado para ser testado - em outras palavras, agradável e limpo.

Eu aconselho você a praticar e emparelhar o programa. Enquanto lê:

Ou, para uma primeira visão geral:

KeesDijk
fonte
4
Tendo acabado de iniciar o teste de unidade, eu teria que concordar. Não apenas é um bom hábito e muito útil combinado com uma abordagem de TDD, mas minimiza tanto tempo. Eu não acho que meus projetos possam ser tão úteis se eu não pudesse executar apenas um teste de unidade e verificar se tudo está funcionando corretamente, mesmo depois de adicionar um novo recurso ou corrigir um bug. Não consigo pensar em fazer testes de regressão de outra maneira.
Kwelch
21
Se os testes de unidade estiverem funcionando como uma documentação, há algo errado. Lendo 500 linhas de código para entender como funcionam cinco linhas de código ao contrário.
Coder
4
@ Codificador: quando você testa métodos de nível superior, envolve muito mais do que 5 linhas de código.
7
@ codificador: a documentação de uma classe informa os serviços que as instâncias da classe fornecem. Ele fornece menos informações sobre como as instâncias dessa classe são usadas no contexto maior, ou seja, a interação entre objetos. Os testes fornecem um código típico de interação em alguns casos, o que tem sido precioso como ponto de partida tantas vezes que nem consigo contar.
Stefano Borini
21
@ Codificador: Não está documentando o que o código faz, está documentando as suposições inerentes a esse código, ou seja, por que e quando deve funcionar. Se as premissas subjacentes forem invalidadas por uma alteração no SUT, um ou mais testes de unidade deverão falhar. Isso não substitui a documentação de design / arquitetura de nível superior, nem mesmo os documentos XML, mas abrange o que essas coisas nunca podem.
Aaronaught
95

Não.

O conceito por trás dos testes de unidade é baseado em uma premissa que se sabe ser falsa desde que o teste de unidade foi inventado: a ideia de que os testes podem provar que seu código está correto.

Ter muitos testes que passam todos prova uma coisa e apenas uma coisa: que você tem muitos testes que passam todos. Não prova que o que os testes estão testando corresponde à especificação. Isso não prova que seu código está livre de erros que você nunca considerou quando escreveu os testes. (E as coisas que você pensou em testar eram os possíveis problemas em que estava se concentrando, então é provável que você as tenha acertado de qualquer maneira!) E por último, mas não menos importante, isso não prova que os testes, que são eles próprios código, estão livres de bugs. (Siga esse último até sua conclusão lógica e você terminará com tartarugas até o fim .)

Djikstra destruiu o conceito de testes como prova de correção em 1988, e o que ele escreveu permanece tão válido hoje:

Agora faz duas décadas desde que foi apontado que o teste do programa pode demonstrar de forma convincente a presença de bugs, mas nunca pode demonstrar sua ausência. Depois de citar essa observação bem divulgada com devoção, o engenheiro de software retorna à ordem do dia e continua refinando suas estratégias de teste, assim como o alquimista de outrora, que continuou refinando suas purificações crisocósmicas.

O outro problema com o teste de unidade é que ele cria um acoplamento rígido entre seu código e o conjunto de testes. Quando você altera o código, espera-se que apareçam alguns erros que quebrariam alguns testes. Mas se você estiver alterando o código porque os requisitos foram alterados, você terá muitos testes com falha e precisará revisar manualmente cada um deles e decidir se o teste ainda é válido. (E também é possível, embora menos comum, que um teste existente que deveria ser inválido ainda passe, porque você esqueceu de alterar algo que precisava ser alterado.)

O teste de unidade é apenas o mais recente de uma longa linha de modismos de desenvolvimento que promete facilitar a gravação de código de trabalho sem ser um bom programador. Nenhum deles conseguiu cumprir sua promessa, e nem essa. Simplesmente não há atalho para realmente saber como escrever código de trabalho .

Existem alguns relatos de testes automatizados sendo realmente úteis nos casos em que a estabilidade e a confiabilidade são de suma importância. Por exemplo, o projeto de banco de dados SQLite. Mas o que é necessário para atingir seu nível de confiabilidade é altamente antieconômico para a maioria dos projetos: uma taxa de código SQLite de teste para real de quase 1200: 1. A maioria dos projetos não pode pagar por isso e nem precisa disso.

Mason Wheeler
fonte
69
Isso prova que seu código se comporta corretamente para esses testes. É muito, se você me perguntar.
Stefano Borini
111
Quem hoje realmente acredita que os testes de unidade são "prova de correção"? Ninguém deve pensar isso. Você está certo de que eles apenas provam que esses testes são aprovados, mas esse é mais um ponto de dados do que você tinha antes de escrever os testes de unidade. Você precisa testar em várias camadas diferentes para ter uma ideia da qualidade do seu código. Os testes de unidade não provam que seu código está livre de defeitos, mas aumentam sua confiança (ou deveria ...) de que o código faz o que você projetou e continua amanhã a fazer o que faz hoje.
Bryan Oakley
40
> but if the test itself is buggy, then you have false confidencee se o testador manual não executar seu trabalho corretamente, você também terá uma confiança falsa.
Stefano Borini
33
@MasonWheeler: desculpe, Mason, não estou convencido. Em mais de duas décadas de programação, acho que nunca vi pessoalmente um caso em que um teste dava uma falsa sensação de segurança. Talvez alguns deles tenham feito e nós os consertamos, mas de nenhuma maneira o custo desses testes de unidade superou os enormes benefícios de tê-los. Se você é capaz de escrever código sem testá-lo no nível da unidade, estou impressionado, mas a vasta e vasta maioria dos programadores por aí não é capaz de fazer isso de forma consistente.
Bryan Oakley
41
Se você escreveu um teste de buggy que seu código passou, é provável que seu código também esteja com bugs. As chances de escrever código de buggy e um teste de buggy são muito inferiores ao código de buggy sozinho. Os testes de unidade não são uma panacéia. Eles são uma boa camada extra (quando prudente) para reduzir a carga dos testadores manuais.
Telastyn
60

Se você já viu o benefício de escrever um método principal para testar algum pequeno pedaço de código da escola, o teste de unidade é a versão profissional / empresarial dessa mesma prática.

Imagine também a sobrecarga da criação do código, iniciando o servidor da Web local, navegando até a página em questão, inserindo os dados ou configurando a entrada para a semente de teste apropriada, enviando o formulário e analisando os resultados ... vs compilação e batida o botão nUnit run.

Aqui está uma imagem divertida também ... insira a descrição da imagem aqui

Encontrei esta imagem aqui:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/

Heath Lilley
fonte
2
Sim você pode. Isole a camada da web em seus testes de unidade para testar a configuração da web (URLS, validação de entrada etc.). Ao stubbing as camadas da web e do banco de dados, você pode testar a camada de negócios sem um banco de dados ou servidor da web. Eu uso o dbunit para testar meu banco de dados. Se você quiser, ainda pode fazer testes de integração total, mas faço isso como uma tarefa específica após o desenvolvimento.
21712 Heath Lilley
12
Gráfico bonito, mas a escala está muito errada. Como apontei na minha resposta, a cobertura completa de testes do SQLite requer aproximadamente 1200x mais código em testes do que o código real no próprio produto. E mesmo que você não seja tão obsessivo com a cobertura total, ainda precisará de várias vezes mais testes que o produto para se aproximar de qualquer nível útil de cobertura em seus testes. Para ser preciso aqui, a parte vertical dessa linha vermelha teria que continuar subindo e subindo e subindo por cerca de três comprimentos de página.
Mason Wheeler
27
@MasonWheeler Esse é um cavalo muito bom que você está batendo, acho que pode ter morrido ... O SQLite tem muitos testes porque é um maldito banco de dados. Eu quero ter certeza de que funciona. Como outro exemplo, a estrutura Silverstripe possui uma proporção de 1: 1 de testes: código, portanto não é como se o SQLite fosse representativo.
Aatch
15
@MasonWheeler Você está falhando no primeiro dos paradoxos de Zenão . Se você quiser dimensionar essa imagem para o nível de teste do SQLite, o eixo X também terá que expandir algo como 100 vezes o seu comprimento atual.
Izkata
2
Isso é especialmente verdade quando você é um desenvolvedor de back-end que não tem tempo para começar a criar uma página da Web em preto e branco apenas para poder testar sua lógica de back-end. Tudo o que tenho que fornecer é fornecer objetos de solicitação e sessão simulados e executar meus controladores através de um teste de unidade, e ao final de tudo sei se está certo ou errado. Se você usar o DI, simplesmente injete um DAO que interaja com um banco de dados na memória para que seu banco de dados não seja alterado ou simplesmente jogue Exceptione cole um para que seus dados não sejam confirmados. Eu digo SIM ao teste de unidade.
Varun Achar
49

Atualmente, o teste de unidade tem uma mística nisso. As pessoas o tratam como se 100% da cobertura de teste fosse um santo graal e como se o teste de unidade fosse a única maneira verdadeira de desenvolver software.

Eles estão perdendo o objetivo.

Teste de unidade não é a resposta. Teste é.

Agora, sempre que essa discussão surgir, alguém (muitas vezes até eu) fará a citação de Dijkstra: "O teste do programa pode demonstrar a presença de bugs, mas nunca demonstra a sua ausência". Dijkstra está certo: o teste não é suficiente para provar que o software funciona como pretendido. Mas é necessário : em algum nível, deve ser possível demonstrar que o software está fazendo o que você deseja.

Muitas pessoas testam à mão. Até os entusiastas do TDD fazem testes manuais, embora às vezes não o admitam. Não pode ser ajudado: pouco antes de você entrar na sala de conferências para demonstrar seu software ao seu cliente / chefe / investidores / etc., Você o percorrerá manualmente para garantir que funcione. Não há nada de errado com isso, e de fato seria louco esperar que tudo corra bem sem executá-lo manualmente - ou seja, testá-lo - mesmo se você tiver 100% de cobertura de teste de unidade e a maior confiança em seus testes .

Mas o teste manual, mesmo que seja necessário para a criação de software, raramente é suficiente . Por quê? Porque o teste manual é tedioso, demorado e realizado por humanos. E os seres humanos são notoriamente ruins em realizar tarefas tediosas e demoradas: evitam fazê-las sempre que possível e geralmente não as fazem bem quando são forçadas a fazê-lo.

As máquinas , por outro lado, são excelentes para executar tarefas tediosas e demoradas. Afinal, foi para isso que os computadores foram inventados.

Portanto, o teste é crucial, e o teste automatizado é a única maneira sensata de garantir que seus testes sejam empregados de forma consistente. E é importante testar e testar novamente, à medida que o software é desenvolvido. Outra resposta aqui observa a importância do teste de regressão . Devido à complexidade dos sistemas de software, alterações freqüentemente aparentemente inócuas em uma parte do sistema causam alterações indesejadas (ou seja, bugs) em outras partes do sistema. Você não pode descobrir essas alterações indesejadas sem alguma forma de teste. E se você deseja ter dados confiáveis ​​sobre seus testes, deve realizar seus testes de maneira sistemática, o que significa que você deve ter algum tipo de sistema de teste automatizado.

O que tudo isso tem a ver com o teste de unidade? Bem, devido à sua natureza, os testes de unidade são executados pela máquina, não por um ser humano. Portanto, muitas pessoas têm a falsa impressão de que o teste automatizado é igual ao teste de unidade . Mas isso não é verdade: os testes de unidade são apenas pequenos testes automatizados.

Agora, qual é o valor em pequenos testes automatizados? A vantagem é que eles testam os componentes de um sistema de software isoladamente , o que permite um direcionamento mais preciso dos testes e ajuda na depuração . Mas o teste de unidade não significa intrinsecamente testes de qualidade superior . Muitas vezes, leva a testes de qualidade mais alta, devido à cobertura do software em um nível mais fino de detalhes. Mas é possível testar completamente o comportamento de apenas um sistema completo, e não suas partes compostas, e ainda testá-lo completamente.

Mas mesmo com 100% de cobertura de teste de unidade, um sistema ainda pode não ser completamente testado. Como os componentes individuais podem funcionar perfeitamente isolados, ainda assim falham quando usados ​​juntos. Portanto , o teste de unidade, embora seja muito útil, não é suficiente para garantir que o software funcione conforme o esperado. De fato, muitos desenvolvedores complementam os testes de unidade com testes de integração automatizados, testes funcionais automatizados e testes manuais.

Se você não vê valor nos testes de unidade, talvez a melhor maneira de começar seja usando um tipo diferente de teste automatizado. Em um ambiente web, o uso de uma ferramenta de teste de automação de navegador como o Selenium geralmente oferece uma grande vitória para um investimento relativamente pequeno. Depois de mergulhar os dedos dos pés na água, você poderá ver com mais facilidade a utilidade dos testes automatizados. E uma vez que você tem testes automatizados, o teste de unidade faz muito mais sentido, pois fornece uma resposta mais rápida do que grandes testes de integração ou de ponta a ponta, pois você pode direcionar testes apenas para o componente em que está trabalhando no momento.

TL; DR: não se preocupe com o teste de unidade ainda. Apenas se preocupe em testar seu software primeiro.

Daniel Pryden
fonte
Os testes de unidade são escritos por humanos também e podem estar errados.
Seun Osewa
41

Depende

Esta é uma resposta que você verá bastante quando se trata de desenvolvimento de software, mas a utilidade dos testes de unidade realmente depende de quão bem eles são escritos. Um número nominal de testes de unidade que verificam a funcionalidade do aplicativo para teste de regressão pode ser bastante útil; no entanto, uma infinidade de testes simples que verificam o retorno das funções pode ser bastante inútil e fornecer uma falsa sensação de segurança, porque o aplicativo "tem muitos testes de unidade".

Além disso, seu tempo como desenvolvedor é valioso e o tempo gasto escrevendo testes de unidade não é o tempo gasto escrevendo novos recursos. Novamente, isso não significa que você não deve escrever testes de unidade, mas todas as funções públicas precisam de um teste de unidade? Eu diria que a resposta é não. O código que está executando a validação de entrada do usuário precisa de teste de unidade? Muito provavelmente, pois é um ponto de falha comum em aplicativos.

Essa é uma daquelas áreas em que a experiência entra em jogo. Com o tempo, você reconhecerá as partes do aplicativo que poderiam se beneficiar do teste de unidade, mas levará algum tempo para chegar a esse ponto.

rjzii
fonte
Este é um bom argumento. Você precisa saber como escrever bons testes que capturam o valor do SUT.
217 Andy
3
Isso basicamente cobre como eu fui ensinado a fazer testes de unidade - escreva testes para cobrir as situações mais importantes / quebráveis ​​primeiro e, em seguida, adicione mais testes quando suas suposições derem errado (eu pensei que algo nunca "poderia falhar", mas aconteceu) .
Brendan Long
38

Os projetos realizados para aulas universitárias diferem muito dos aplicativos de negócios que você escreverá no seu trabalho. A diferença é vida útil. Quanto tempo o projeto universitário "vive"? Na maioria dos casos, começa quando você escreve a primeira linha do código e termina quando recebe a sua marca. Você poderia dizer que, efetivamente, ele vive apenas pelo tempo de implementação. "Liberação" é geralmente igual à sua "morte".

O software desenvolvido para os negócios ultrapassa esse ponto de morte do projeto da universidade e continua a viver enquanto os negócios precisarem. O que é muito longo . Quando se fala em dinheiro, ninguém gasta um centavo quebrado para ter um "código mais legal e organizado". Se o software escrito em C há 25 anos ainda funciona e é bom o suficiente (conforme entendido pelas necessidades do proprietário da empresa), espera-se que você o solicite para mantê-lo (adicionando novos recursos, melhorando os antigos - alterando o código-fonte ).

Chegamos a um ponto muito importante - regressão . No local em que trabalho, temos duas equipes mantendo dois aplicativos; um, escrito há cerca de 5 a 6 anos, com muito pouca cobertura para testes de código *, e segundo, versão mais recente do primeiro aplicativo com conjunto de testes completo (unidade, integração e o que não mais). Ambas as equipes têm testadores manuais (humanos) dedicados. Deseja saber quanto tempo leva para introduzir um novo recurso bastante básico para a primeira equipe? 3 a 4 semanas. Metade desse tempo está "verificando se tudo ainda funciona". Este é um tempo ocupado para testadores manuais. Os telefones estão tocando, as pessoas ficam chateadas, algo está quebrado de novo. A segunda equipe geralmente lida com esses problemas em menos de 3 dias.

Eu nunca digo que os testes de unidade tornam seu erro de código propenso, correto ou outras palavras sofisticadas que você pode criar. Nem eles fazem os erros desaparecerem magicamente. Porém, quando combinados com outros métodos de teste automatizado de software, eles tornam os aplicativos muito mais fáceis de manter do que teriam sido. Esta é uma grande vitória.

E por último, mas não menos importante, comentário de Brian, que acho que trata da questão toda:

(...) eles aumentam sua confiança (ou deveriam ...) de que o código faz o que você projetou e continua amanhã a fazer o que faz hoje.

Porque entre hoje e amanhã, alguém pode fazer pequenas alterações, o que causará uma falha no código do gerador de relatórios tão importante . Os testes aumentam as chances de que você descubra isso antes que o cliente faça um pouco do seu lado.

* Eles introduzem lentamente mais e mais testes em sua base de código, mas todos sabemos como essas coisas geralmente se parecem.

km
fonte
10
+1000 para vincular a Software_Regression. As faculdades expõem os testes de unidade como algo que você deve fazer por pura fé, sem explicar em detalhes que existe uma doença para prevenir e controlar e que essa doença é chamada de regressão . (depois há o problema com testes de regressão sendo algo muito diferente de testes de unidade, para que a única leitura que eu encontrei explicá-lo bem é a amostra grátis deste livro )
ZJR
25

está escrevendo testes de unidade para formulários da Web do ASP.NET, algo que é feito com frequência e se: como resolver o problema do "ambiente dinâmico"?

Isso nem sempre é feito. Trabalhar com elementos da interface do usuário não é bom para os testes de unidade, pois não há uma maneira excelente de verificar programaticamente se as coisas certas acabam na tela nos lugares certos.

Vocês me aconselhariam a começar a escrever testes de unidade? Eu acho que isso pode me ajudar na implementação real, mas, novamente, eu sinto que isso pode me atrasar.

Onde aplicável, sim. Eles podem ser muito úteis na verificação de casos específicos de maneira repetível. Eles ajudam a agir como 'atrito' contra mudanças problemáticas e como à prova de falhas quando você está fazendo mudanças melhores.

Uma coisa a notar é que eles geralmente o atrasam.

Esta certo.

Passar um pouco de tempo agora (se bem feito) economizará seu tempo no futuro, pois eles detectam alguns erros, evitam a repetição de alguns erros e permitem que você se sinta um pouco mais confortável ao fazer outras melhorias no código para impedir que ele apodreça.

Telastyn
fonte
8
+1 para realmente responder ao caso de uso da pergunta! Todo mundo pulou na parte "teste de unidade" e esqueceu a parte "formulários da web do ASP.NET" ...
Izkata
1
Essa é uma ótima resposta e merece mais votos, porque você respondeu às perguntas e foi honesto ao avaliar a velocidade do desenvolvedor e não prometer que todos os erros serão detectados ou evitados, o que é completamente e totalmente verdade.
Mantorok
11

Acabei de me formar em CS e atualmente tenho um emprego como desenvolvedor júnior de .NET (em C # e geralmente ASP.NET, formulários da web - não ASP.NET MVC). Quando eu ainda estava na universidade, o assunto dos testes de unidade era abordado, mas eu nunca vi os benefícios disso.

Isso porque você nunca programou muito.

Eu entendo o que ele deve fazer - determinar se um bloco de código é ou não adequado para uso - mas eu nunca tive que escrever um teste de unidade antes. (nem> eu já senti a necessidade de ..)

Escrever testes de unidade força seu código a se adaptar a uma determinada estrutura mental que é testável, bem documentada e confiável. É muito mais do que você afirma.

-Eu li que o teste de unidade geralmente acontece através da escrita de "zombarias". Embora eu entenda esse conceito, não consigo descobrir como devo escrever zombarias para sites completamente dinâmicos e onde quase tudo depende dos dados provenientes de um banco de dados.

simule o acesso ao banco de dados com uma classe simulada que retorna classes de modelo preenchidas com dados bem definidos e codificados. ou preencha um banco de dados de teste com dados do equipamento e trabalhe a partir daí.

- Vocês me aconselham a começar a escrever testes de unidade?

Claro que sim. Leia o "Test Driven Development" de Beck primeiro.

Eu acho que isso pode me ajudar na implementação real, mas, novamente, eu sinto que isso pode me atrasar.

Isso deixa você mais lento agora. Mas quando você precisar depurar por horas em vez de dias, você mudará de idéia.

Qualquer conselho será apreciado :)

Teste. Confie em mim. Infelizmente, também deve ser uma política de gerenciamento, mas é algo que economiza tempo. Os testes permanecem, eles estão lá, agora e no futuro. Quando você altera a plataforma e executa os testes, e eles ainda funcionam, você sabe que seu material funciona conforme o esperado.

Stefano Borini
fonte
8

Edit: É claro que entrei para o TDD pro / con dogpile e pulei a pergunta 1:

1 - Implementando testes de unidade nos formulários da web ASP.net:

Primeiro de tudo, se você acha que pode levá-los ao MVC, lute por ele como um urso da caverna raivoso. Como desenvolvedor front-end / UI, o .net MVC foi o que me ajudou a parar de odiar o .net, para que eu pudesse me concentrar melhor em odiar todas as soluções da Web em Java que já encontrei. Os testes de unidade são problemáticos porque os formulários da Web realmente desfocam as linhas entre o servidor e o lado do cliente. Em qualquer tentativa de fazer testes de unidade, eu colocaria o foco na manipulação de dados e (esperançosamente) presumiria que os formulários da web tratam da normalização da entrada do usuário para você.

2 - Se os testes de unidade valem a pena em primeiro lugar:

Tudo bem, divulgação completa:

  • Eu sou principalmente autodidata. Meu treinamento formal se resume a uma classe JavaScript, PHP e C # e meu próprio estudo pessoal dos princípios de POO e leitura de coisas como Design Patterns.

Contudo,

  • Eu escrevo principalmente para a web do lado do cliente e a parte real da programação está em uma das linguagens mais rápidas e soltas disponíveis no que diz respeito à digitação dinâmica, funções de primeira classe e mutabilidade de objetos.

Isso significa que não escrevo para o mesmo compilador ou máquina virtual. Eu escrevo para 4-20 interpretações variadas de três idiomas (sim, dois deles meramente declarativos, mas também determinam o espaço físico fundamental da interface do usuário com o qual estou trabalhando de maneiras diferentes às vezes) e o faço desde que as interpretações foram um muito mais variado do que é hoje. E não, eu não sou apenas um garoto que conecta coisas do JQuery para aplicativos descartáveis. Ajudo a criar e manter coisas bastante sofisticadas com muita complexidade de elementos de interface do usuário.

Portanto, sim, existem muitas oportunidades para alguns ajustes aqui e ali para criar uma cascata maciça de falhas se suas habilidades de design forem uma porcaria completa ou se você estiver jogando devs medíocres em grandes quantidades com 1-2 problemas de qualidade.

Meu entendimento do que o TDD deve fazer por você é que os testes são realmente mais para forçar você a considerar o design com mais cuidado e manter o foco nos requisitos. É justo, mas o problema aqui é que ele subverte o que você deve fazer, que é o design para uma interface, para algo sutil, mas fundamentalmente diferente, que é o design para testes de uma interface. A diferença para mim é entre desenhar uma imagem clara de que a mamãe não terá que adivinhar o significado e preencher a página inteira com verde muito rápido, para que você possa ser o primeiro garoto a dar um tapa na mesa e gritar "pronto!" " Ao mudar a prioridade dos resultados sobre o processo e o design, você basicamente incentiva a implementação contínua do código de lixo, que é o que estava na raiz dos seus problemas em primeiro lugar.

E, claro, há o benefício secundário "não é o ponto real", mas frequentemente elogiado, dos próprios testes de unidade, ajudando a detectar erros de regressão. Os defensores do TDD tendem a ser um pouco insolentes sobre se esse é realmente o objetivo ou apenas um efeito colateral bacana, a IMO, porque eles sabem muito bem ou suspeitam pelo menos que isso simplesmente não é suficiente para estabelecer a ausência de bugs no seu código, especialmente em uma linguagem mais dinâmica como JavaScript, na qual supor que você possa prever todos os cenários possíveis em uma longa cadeia de dependências é imprudente.

Há um local para testes automatizados em JS, mas um uso muito melhor do seu tempo do que anexar um teste de unidade a cada 'unidade' do seu código que entra em contato com outro é garantir que você não tenha muitos objetos de lixo que duplicam o trabalho ou cujo uso pretendido é semanticamente ambíguo nele, em primeiro lugar. Você segue o princípio DRY. Você abstrai as coisas para reutilização / portabilidade quando o valor de fazer isso se torna aparente (e nem um minuto antes). Você estabelece processos consistentes e maneiras de fazer as coisas seguindo mais o princípio da cenoura do que da vara (ou seja, é muito fácil usar suas coisas da maneira certa para se incomodar em querer fazer da maneira errada). E pelo amor de todas as coisas, foo and bar, você nunca se envolve em enormes padrões de esquemas de herança em cascata como um meio de reutilização de código.

Todas as opções acima me ajudaram a reduzir os erros difíceis de diagnosticar no meu código de maneira séria e você pode confiar que é uma grande prioridade para alguém que surgiu como desenvolvedor com um conjunto de navegadores que não tinha nada melhor para lhe dizer do que " uh, houve um problema com um objeto do tipo 'Objeto' neste número de linha imaginário em um arquivo não especificado. " (caramba, obrigado IE6) O TDD, na minha linha de trabalho, não incentivaria essas coisas. Mudaria o foco para 100% de resultados sobre o processo, onde o que está entre os pontos A e B não importa realmente, desde que funcione. É um desperdício de tempo que seria melhor aplicado para garantir que seu material seja legível, portátil e fácil de modificar, sem muita quebra de confusão em primeiro lugar.

Ou talvez eu esteja apenas sendo excessivamente mesquinho sobre o paradigma em que estou enraizado, mas, em minha opinião, fazer isso da maneira certa é um uso muito mais eficaz do tempo do que cobrir sua bunda quando você ou todos os outros equipe faz errado. E nada deve forçá-lo a considerar o design, apenas implementando as coisas. O design deve ser o altar de todo programador. E qualquer coisa que "o force" a fazer a coisa certa ou o proteja de si mesmo deve ser vista com a mesma suspeita reservada a garrafas de óleo de cobra, a IMO. O óleo de cobra na TI moderna e no desenvolvimento geral, se você ainda não sabe, é vendido por tonelada líquida.

Erik Reppen
fonte
1
Eu escrevo muitos testes de unidade. Não vou escrever código sem eles. Mas eu concordo com seus sentimentos. Os testes devem orientar , não impulsionar o desenvolvimento. Você não pode automatizar o pensamento cuidadosamente sobre um problema.
FizzyTea 26/07/12
Não tenho nenhum problema com testes automatizados. Mas as adoções por atacado a cada momento parecem mais pânico do que processo para mim. Economizar esse tempo para projetar e automatizar testes e validação em pontos em que é provável que você interaja com várias coisas que não controla é como eu prefiro.
precisa
5

Na minha experiência, os testes de unidade são realmente muito úteis quando você começa com eles e permanece com eles, isto é, Desenvolvimento Orientado a Testes. Aqui está o porquê:

  • Os testes de unidade forçam você a pensar sobre o que deseja e como verificar se o conseguiu, antes de escrever o código . Em um cenário TDD, você escreve o teste primeiro. Portanto, você precisa saber o que o código que você está prestes a escrever precisa fazer e como verificar se ele foi bem-sucedido, para escrever um teste "vermelho" que você torna "verde" escrevendo o código em passe isso. Em muitos casos, isso força você a pensar um pouco mais sobre o algoritmo que está prestes a escrever para passar neste teste, o que é sempre bom, pois reduz erros de lógica e "casos de canto". Enquanto você está escrevendo o teste, está pensando "como isso pode falhar" e "o que não estou testando aqui", o que leva a um algoritmo mais robusto.

  • Os testes de unidade forçam você a pensar em como o código que você está prestes a escrever será consumido . Antes de aprender o TDD, houve MUITAS vezes em que escrevi código esperando que uma dependência funcionasse de uma maneira e depois recebi uma dependência escrita por um colega que trabalhava de uma maneira completamente diferente. Embora isso ainda seja possível com o TDD, o teste de unidade que você está escrevendo o força a pensar em como você deseja usar o objeto que está escrevendo, porque é um exemplo de uso do referido objeto. Esperamos que você escreva o objeto de maneira que seja fácil de consumir e, portanto, se adapte, se necessário (embora a programação para interfaces predefinidas seja uma solução geral melhor para esse problema que não requer TDD).

  • Os testes de unidade permitem "codificar por teste" . Uma ferramenta de refatoração como o ReSharper pode ser sua melhor amiga, se você permitir. Você pode usá-lo para definir o esqueleto da nova funcionalidade enquanto define o uso em um teste.

    Por exemplo, suponha que você precise criar um novo objeto MyClass. Você começa criando uma instância do MyClass. "Mas o MyClass não existe!", Reclama ReSharper. "Então crie", você diz, pressionando Alt + Enter. E pronto, você tem sua definição de classe. Na próxima linha do código de teste, você chama um método MyMethod. "Mas isso não existe!", Diz ReSharper. "Então crie", você repete, com outro Alt + Enter. Com algumas teclas pressionadas, você definiu o "esqueleto" do seu novo código. À medida que você aprimora o uso, o IDE avisa quando algo não se encaixa, e geralmente a solução é simples o suficiente para que o IDE ou uma ferramenta que se conecte a ele saiba como corrigi-lo.

    Exemplos mais extremos estão em conformidade com o modelo "Triple-A"; "Organize, aja, afirme". Configure tudo, execute a lógica real que você está testando e depois afirme que a lógica está correta. Codificando dessa maneira, é muito natural codificar a solução no teste; depois, com algumas teclas pressionadas, você pode extrair essa lógica e colocá-la em algum lugar onde possa ser usada no código de produção, e depois fazer pequenas alterações no teste que apontam para o novo local da lógica. Fazer isso dessa maneira obriga a arquitetar o código de maneira modular e fácil de reutilizar, porque as unidades que você está testando ainda devem estar acessíveis.

  • Os testes de unidade executam muitas ordens de magnitude mais rapidamente do que qualquer teste manual que você possa imaginar. Há um ponto, muito rapidamente atendido no caso de projetos maiores, em que o tempo gasto em testes de unidade começa a se pagar, reduzindo o tempo gasto em testes manuais. Você sempre deve executar o código que acabou de escrever. Tradicionalmente, você fazia isso manualmente, iniciando um programa grande, navegando pela interface do usuário para configurar a situação para a qual alterou o comportamento e depois verificando os resultados novamente através da interface do usuário ou na forma de dados produzidos. Se o código tiver TDD, basta executar os testes de unidade. Garanto que, se você estiver escrevendo bons testes de unidade, a última opção será muitas vezes mais rápida que a anterior.

  • Testes de unidade capturam regressão . Novamente, houve muitas vezes antes que eu aprendesse TDD em que entrei, fiz o que eu pensava ser uma mudança cirúrgica em um pedaço de código, verifiquei que a mudança corrigia um comportamento incorreto (ou produzia um novo comportamento desejado) na situação relatada , e fez o check-in para liberação, apenas para descobrir que a alteração quebrou outro caso de canto em um módulo completamente diferente que, por acaso, reutilizou o mesmo bloco de código. Em um projeto TDDed, eu posso escrever um teste para verificar uma alteração que estou prestes a fazer, fazer a alteração e executar o conjunto completo. Se todos os outros usos do código foram TDDed e minha alteração quebrou alguma coisa, os testes para esses outras coisas vão falhar, e eu posso investigar.

    Se os desenvolvedores precisassem encontrar e testar manualmente todas as linhas de código que poderiam ser afetadas por uma alteração em potencial, nada seria feito porque o custo de determinar o impacto de uma alteração tornaria a alteração inviável. No mínimo, nada seria SÓLIDO e, portanto, facilmente mantido, porque você nunca ousaria tocar em algo que possa ser usado em vários lugares; em vez disso, você lançaria sua própria solução de alteração muito semelhante, mas incorporando sua menor para este caso, violando o SRP e provavelmente o OCP, e lentamente transformando sua base de código em uma colcha de retalhos.

  • Os testes de unidade moldam a arquitetura de uma maneira tipicamente vantajosa . Testes de unidade são testes executados isoladamente de qualquer outra lógica. Para poder testar seu código de unidade, você deve escrever o código da maneira que puderisolá-lo. Boas decisões de projeto, como acoplamentos frouxos e injeção de dependência, eliminam naturalmente o processo TDD; as dependências devem ser injetadas para que, em um teste, você possa injetar um "mock" ou "stub" que produza a entrada ou manipula a saída para a situação que está sendo testada sem criar "efeitos colaterais". A mentalidade de "primeiro uso" do TDD geralmente leva à "codificação para interfaces", a essência do acoplamento flexível. Esses bons princípios de design permitem que você faça alterações na produção, como substituir uma classe inteira, sem exigir que grandes quantidades da base de código sejam alteradas para se adaptar.

  • Testes de unidade mostram que o código funciona, em vez de provar que o código funciona . À primeira vista, você pode pensar que é uma desvantagem; certamente a prova é melhor que a demonstração? A teoria é ótima; teoria computacional e algorítmica é a base do nosso trabalho. Porém, uma prova matemática de correção de um algoritmo não é prova de correção da implementação . Uma prova matemática mostra apenas que o código aderente ao algoritmo deve estar correto. Um teste de unidade mostra que o código realmente escrito faz o que você pensou que faria e, portanto, é prova de que está correto. Isso geralmente tem muito mais valor do que uma prova teórica.

Agora, tudo o que foi dito, há desvantagens no teste de unidade:

  • Você não pode testar tudo. Você pode arquitetar seu sistema para minimizar o número de LOC não cobertos por um teste de unidade, mas simplesmente haverá certas áreas do sistema que não podem ser testadas em unidade. Sua camada de acesso a dados pode ser ridicularizada quando usada por outro código, mas a própria camada de acesso a dados contém muitos efeitos colaterais e, normalmente, não é viável fazer o teste de unidade muito (a maioria?) De um Repositório ou DAO. Da mesma forma, o código que usa arquivos, configura conexões de rede etc. tem efeitos colaterais integrados e você simplesmente não pode testar a unidade de linha de código que faz isso. Os elementos da interface do usuário geralmente não podem ser testados em unidade; você pode testar os códigos por trás de métodos como manipuladores de eventos, pode construir construtores de teste de unidade e verificar se os manipuladores estão conectados, mas simplesmente não há substituto no código para um usuário clicar com o mouse em um elemento gráfico específico e assistir ao chamado do manipulador. Atingir esses limites entre o que pode e o que não pode ser adequadamente testado em unidade é chamado de "raspar a borda da caixa de areia"; além desse ponto, você está limitado ao uso de testes de integração, testes de aceitação automatizados e testes manuais para verificar o comportamento.

  • Muitas vantagens do teste de unidade não se aplicam sem TDD. É perfeitamente possível escrever código, depois escreva testes que exercitam o código. Eles ainda são "testes de unidade", no entanto, ao escrever o código primeiro, você perde muitas das vantagens inerentes ao desenvolvimento do "teste primeiro": o código não é necessariamente arquitetado de uma maneira que possa ser facilmente testada ou mesmo usada na produção. ; você não recebe o processo de "verificação dupla" inerente ao escrever o teste e pensar no que você não estava pensando; você não codifica testando; e se você escrever um código, teste-o manualmente e veja-o funcionar; em seguida, codifique um teste de unidade que falha, o que está errado, o código ou o teste? Suas principais vantagens são a prevenção de regressão (você será alertado quando o código que passou anteriormente em seus testes agora falhar) e a verificação em alta velocidade em comparação aos testes manuais. A perda de TDD '

  • O teste de unidade introduz uma sobrecarga . Simplesmente, você está escrevendo um código para testar o código que está escrevendo. Isso necessariamente aumentará o LOC total de um projeto de desenvolvimento e, sim, o LOC para testes pode exceder o LOC do projeto real. Desenvolvedores e não desenvolvedores ingênuos analisarão esse estado de coisas e dirão que os testes são uma perda de tempo.

  • O teste de unidade requer disciplina. É necessário escrever testes que exercitem adequadamente a base de código (boa cobertura de código), executar regularmente (como sempre que você fizer uma alteração, o conjunto completo deve ser executado) e manter tudo "verde" ( todos os testes foram aprovados). Quando as coisas quebram, você deve corrigi-las fixando o código que não atende às expectativas ou atualizando as expectativas dos testes. Se você alterar os testes, deverá perguntar "por que" e vigiar muito bem a si mesmo; é incrivelmente tentador simplesmente alterar afirmações com falha para corresponder ao comportamento atual ou simplesmente remover testes com falha; mas, esses testes devem se basear nos requisitos e, quando os dois não correspondem, você tem um problema. Se essas coisas não forem feitas,

  • O teste de unidade requer mais equipamentos. A solução usual para a necessidade de disciplina acima, e uma tendência natural dos humanos de se tornarem preguiçosos e compactos, é um "build-bot" executando um pacote de software de "Integração Contínua", como TeamCity, CruiseControl, etc., que executa testes de unidade, calcula métricas de cobertura de código e possui outros controles, como "triple-C" (conformidade de convenção de codificação, à la FxCop). O hardware para o build-bot deve ter um desempenho razoavelmente bom (caso contrário, não acompanhará a taxa de check-ins de código que a equipe média fará), e os procedimentos de check-in no bot devem ser atualizados (se uma nova biblioteca de testes de unidade é criada, scripts de construção que executam testes de unidade devem ser alterados para procurar nessa biblioteca). Isso é menos trabalho do que parece, mas normalmente requer algum conhecimento técnico por parte de pelo menos algumas pessoas da equipe que sabem como funcionam os detalhes de vários processos de construção (e, portanto, podem automatizá-los em scripts e manter esses scripts). Também requer disciplina na forma de prestar atenção quando a compilação "quebrar" e corrigir o que causou a compactação (corretamente) antes de fazer o check-in de algo novo.

  • O teste de unidade pode forçar a arquitetura do código de maneira não ideal . Embora o TDD seja tipicamente bom para a modularidade e reutilização do código, pode ser prejudicial à acessibilidade adequada do código. Objetos e membros, colocados em bibliotecas de produção, não podem ser privados ou internos se forem usados ​​diretamente por testes de unidade. Isso pode causar problemas quando outros codificadores, agora vendo um objeto, tentam usá-lo quando deveriam usar algo mais presente na biblioteca. As revisões de código podem ajudar com isso, mas podem ser uma preocupação.

  • O teste de unidade geralmente proíbe estilos de codificação de "desenvolvimento rápido de aplicativos". Se você está escrevendo testes de unidade, não está codificando "rápido e solto". Isso normalmente é uma coisa boa, mas quando você está dentro de um prazo imposto fora do seu controle ou está implementando uma mudança de escopo muito pequeno, e a parte interessada (ou seu chefe) está se perguntando por que todo esse lixo deve acontecer apenas para alterar uma linha de código, pode ser inviável escrever e manter o conjunto de testes de unidade adequado. Os processos ágeis geralmente ajudam nisso, permitindo que os desenvolvedores digam os requisitos de tempo; lembre-se, tudo o que o vendedor precisa fazer é dizer "sim, podemos" e eles recebem a verificação da comissão, a menos que o processo envolva as pessoas que realmente precisam fazer o trabalho dizendo "não, não podemos" e prestando atenção. Mas nem todos são ágeis e o Agile tem suas próprias limitações.

KeithS
fonte
4

Testes de unidade são úteis quando usados ​​corretamente; Existem vários problemas com sua lógica.

"Quando estou desenvolvendo, passo por muitas tentativas e erros", disse Kevin.

Veja a programação por coincidência. É melhor entender o que um código deve fazer e provar que ele é feito através de um teste de unidade. Não assuma que um código funcione simplesmente porque a interface do usuário não quebrou quando você executou o programa!

s writing unit tests for ASP.NET web forms something that is done often

Não tenho conhecimento de dados estatísticos para dizer com que frequência as pessoas testam formulários da web. Isso não importa. A interface do usuário é difícil de testar e os testes de unidade também não devem ser acoplados a uma interface do usuário. Separe sua lógica em camadas, bibliotecas de classes que podem ser testadas. Teste a interface do usuário separadamente da lógica de back-end.

So, question number 2: Would you guys advise me to start writing unit tests?

Sim. Depois que você se acostuma, eles aceleram você. A manutenção é muito mais demorada e cara do que a fase inicial de desenvolvimento. A manutenção é muito auxiliada nos testes de unidade, mesmo nos testes iniciais e na correção de erros.

P.Brian.Mackey
fonte
Existem estruturas de teste por aí que podem fazer testes em páginas aspx para simplesmente testar se as páginas são carregadas com êxito ou não em diferentes cenários. Isso pode não ser bom o suficiente, mas é melhor que nada.
temor
4

Em um nível prático, os testes de unidade podem ser extremamente úteis por um motivo muito importante: você pode testar um bit de código por vez.

Quando você está escrevendo uma sequência inteira de etapas complexas e as depura no final, você tende a encontrar muitos erros, e o processo geralmente é mais difícil porque você está mais adiantado no processo. No Visual Studio, você pode gerar um teste rápido, alterá-lo um pouco e executar APENAS esse teste . Você sabe que, por exemplo, um método que chama esse método pode confiar nele. Portanto, aumenta a confiança.

Os testes de unidade não provam que seu programa está correto! : Os testes de unidade verificam regressões no código confidencial e permitem testar novos métodos que você escreve.

Os testes de unidade não têm como objetivo testar os front-ends : pense em um teste de unidade como o pequeno projeto que você cria para testar um novo método que você está escrevendo ou algo assim, não como um tipo de condição que seu código precisa atender.

O teste de unidade funciona muito bem em ambientes colaborativos : se eu tiver que fornecer um método para um colega que está usando uma tecnologia completamente diferente da minha, como, por exemplo, ele está chamando a partir do iOS, eu posso escrever rapidamente um teste de unidade para ver se o método que ele deseja a) Recupera os dados corretos b) Executa de acordo com suas especificações c) Não possui gargalos desagradáveis.

Tjaart
fonte
"Os testes de unidade não se destinam a testar front-ends" Quem disse isso? Eu não estou questionando isso. Eu gostaria de saber porque muitas pessoas parecem ter a ideia errada e gostaria de dar uma palmada com o que não é o que essa fonte de advogado-TDD-fonte-imensamente-influente-diz.
precisa
Algumas pessoas, inclusive eu, tiveram esse conceito errado ao encontrar os testes de unidade, então estou apenas esclarecendo isso. Não sei por que você sente que estou desafiando você. Na verdade, concordo plenamente com você.
Tjaart
4

Uma coisa que parece não ser abordada é a complexidade de testar diferentes tipos de código.

Quando você lida com itens com entradas e saídas simples, geralmente é fácil fazer o teste de unidade e, se os testes forem escolhidos tendo em mente os casos extremos do código que está sendo testado, eles lhe darão muita confiança de que estão certos. Não escrever testes para esse código seria uma loucura. (Observe que a maioria dos códigos inseridos nas bibliotecas atende a esse critério.)

No entanto, em outros casos, você acaba criando enormes simulações para testar, porque o código está reproduzindo dados subjacentes complexos (geralmente um banco de dados, mas não precisa ser) ou produz dados de saída muito complexos (pense em uma rotina que muda um valor inicial em um nível de jogo para um exemplo bastante extremo) e o teste de unidade não é tão útil. Cobrir tudo em seus casos de teste geralmente é um sonho, e quando você encontra um bug, quase sempre é um caso em que você nunca pensou e, portanto, não poderia ter construído um teste para isso.

Não há balas de prata, qualquer coisa retratada como uma bala de prata não é tão boa quanto afirmam os defensores, mas isso não significa que seja inútil.

Loren Pechtel
fonte
4

Escrever testes de unidade para aplicativos de formulários da Web do ASP.NET NÃO é comum e muito difícil de realizar. No entanto, isso não significa que o projeto deve ignorá-lo.

Os testes de unidade são corner stonesaplicativos de missão crítica e fornecem confiabilidade e tranquilidade de que a funcionalidade principal executa conforme o esperado.

Na verdade, você pode introduzir testes de unidade com muito mais facilidade com um padrão ASP.NET MVP que pode ser usado no desenvolvimento de formulários da web. Introduzirá separação de preocupações e ability to write essential unit tests.

Algumas referências que podem ser úteis para procurar são:

ElYusubov
fonte
2
+1 Não importa se você está fazendo testes de unidade ou não, o MVP é o caminho a percorrer ao trabalhar com Web Forms (talvez WinForms também).
simoraman
3

O objetivo dos testes de unidade é permitir que você altere seu código com segurança (refatoração, aprimoramento etc.) sem o medo de poder quebrar algo dentro do sistema. Isso se mostra muito útil para aplicativos grandes, quando você realmente não conhece todos os efeitos de sua alteração de código (apesar do acoplamento fraco).

m3th0dman
fonte
6
Sem medo é uma falsa sensação de segurança.
Coder
Talvez "menos medo" seja uma frase melhor, mas a resposta ainda está amplamente correta.
Brendan Long
1
@ Codificador Se seus testes passarem após a refatoração, você poderá ter certeza de que a melhoria no código não mudou a maneira como o aplicativo se comporta (grosso modo, você não introduziu nenhum novo bug, mas isso não é necessariamente verdade porque você não pode obter 100% de cobertura de teste).
M3th0dman
2

É minha experiência que sim , testes de unidade são úteis.

O Teste de Unidade trata da segregação de partes do código que você escreve e garante que elas funcionem isoladamente. Esse isolamento pode realmente envolver a criação de objetos falsos ou simulados para conversar com o objeto que você está testando, ou não. Depende muito da arquitetura do seu objeto.

O teste de unidade concede vários benefícios:

Principalmente, isso garante que as unidades testadas funcionem da maneira que você, desenvolvedor, acha que elas devem funcionar. Embora isso seja menor do que parece: não significa necessariamente que o objeto esteja funcionando corretamente; só que está funcionando como você acha que deve funcionar, é uma afirmação muito mais forte do que o método de tentativa e erro necessário sem o teste de unidade.

Além disso, garante que as unidades continuem funcionando da maneira que você, o desenvolvedor, pensou que deveria funcionar. O software é alterado e isso pode afetar as unidades de maneiras inesperadas.

Outro efeito colateral é que isso significa que as unidades que testam fazer o trabalho de forma isolada. Isso geralmente significa que você começa a programar para interfaces em vez de classes concretas, reduzindo o acoplamento e aumentando a coesão: todas as características comuns do bom design. Sim: apenas permitir que suas unidades de código tenham testes de unidade naturalmente melhorará o design do seu código.

Contudo...

O teste de unidade não é o fim do teste. Outros tipos de teste ainda são necessários. Por exemplo, mesmo quando você mostra que as unidades funcionam da maneira que você espera que funcionem, você ainda precisa mostrar que cada unidade funciona da maneira que as unidades que falam com ela esperam que funcione. Ou seja, seus componentes se integram corretamente?

Kaz Dragon
fonte
1

Para aplicativos simples com um pequeno número de camadas para testar (Janela principal -> submenu), talvez seja necessário compilar para executar para verificar as alterações.

Para aplicativos maiores, nos quais é necessária uma navegação de 30 anos para acessar a página que você está testando, isso acaba sendo muito caro.

DefenestrationDay
fonte
1

Quero adicionar um novo lado (na verdade um antigo) a isso: testes de unidade não são tão úteis se o seu código for bem projetado .

Sei que a maioria dos programadores não faz mais o design de programas, ainda o faço, e achei os testes de unidade uma necessidade bastante demorada para se encaixar em uma cultura TDD, mas até agora, só encontrei 1 a 2 menores bugs por milhares de linhas de testes do meu código - não apenas o que escrevi, mas o que os testadores oficiais também escreveram.

Eu acho que você também não fará mais o design de programas - o pessoal atual o pressionará para que não o faça -, mas talvez valha a pena lembrar que o teste de unidade é um método de eficiência muito, muito baixa, comparado ao design.

Este é um argumento dijsktraiano: o teste de unidade só pode ser executado em um programa que seja detalhado o suficiente para ser executado.

Se você desenhar fluxogramas / diagramas de estado / ação, diagramas de seqüência, inventários de objetos (e último E menos, diagramas de classe) para o seu código antes de realmente escrevê-lo, poderá eliminar a maioria dos bugs potencialmente ameaçadores apenas rastreando suas linhas e verificando seus nomes.

Atualmente, os diagramas de classes são gerados a partir do código, contendo centenas, às vezes milhares de classes e são completamente inutilizáveis ​​- qualquer coisa que contenha mais de 15 elementos está além do reconhecimento humano.

Você precisa saber o que 10 + -5 classes importam ou o que você faz no momento e poder verificar seu código de vários pontos de vista, cada diagrama representando EXATAMENTE os pontos de vista que você está vendo, e você eliminará milhares de bugs no papel.

  • Verificar um código dinâmico se os tipos forem atendidos (apenas mostrar tipos de entrada / saída em um fluxograma e conectá-los a um lápis ou cor diferente),
  • verificando se todos os estados são tratados (verificando a plenitude de suas condições),
  • rastreando as linhas para garantir que tudo termine (todo fluxograma deve ser um automático de estado finito determinístico totalmente definido, para as pessoas que pensam matematicamente
  • garantir que certos componentes não tenham nada a ver um com o outro (extraindo todas as suas dependências) (bom para segurança)
  • simplificando o código convertendo dependências em associações (dependências são de quais classes os métodos membros usam)
  • verificando nomes, procurando prefixos comuns, apagando sinônimos etc.

há muito mais fácil ...

Além disso, descobri que meus aplicativos são mais utilizáveis, se vierem diretamente de casos de uso ... se os casos de uso foram escritos corretamente (assunto do verbo ACTOR, o Mantenedor solicita a abertura do caixa eletrônico) ...

Eu fiz código com 95% + de coberturas de código. Claro, às vezes faço testes de unidade, esp. para verificações de limites nos cálculos, mas ainda não encontrei regressões sérias (sérias: não são eliminadas em 24 horas) por não usar testes de unidade, mesmo para refatorações.

Às vezes eu não faço uma única linha de código por 3-4 dias seguidos, apenas desenhando. Então, em um dia, digito 1500-2000 linhas. No dia seguinte, a maioria está pronta para produção. Às vezes, os testes de unidade são escritos (com mais de 80% da cobertura), às vezes (além disso) os testadores são solicitados a tentar quebrá-lo, toda vez que algumas pessoas são solicitadas a revisá-lo olhando para ele.

Ainda estou para ver esses testes de unidade encontrando alguma coisa.

Eu gostaria que o pensamento de design substituísse o TDD ... mas o TDD é muito mais fácil, é como ir com uma marreta ... o projeto precisa de pensamento, e você fica fora do teclado na maioria das vezes.

Aadaam
fonte
Eu acho que você pode desenhar no teclado. Mas planejar e organizar o código exige muito mais pensamento do que simplesmente tropeçar na entrada e na saída em classes que também podem ser funções monolíticas.
precisa
Confie em mim, as funções monolíticas não cabem em um papel A4 (ou US Letter). Às vezes, quando tenho preguiça, faço "design" no teclado, mas essa não é a mesma qualidade. Sempre que desenvolvo um projeto sério, faço design com UML. Quando você desenha isso, tenta explicar a si mesmo e aos outros de uma maneira muito restrita, mas ainda estruturada, o que está acontecendo e, quando é capaz de explicar o código de todas as perspectivas, só então você digita -lo, e de repente todos os seus erros são na maioria dos erros de digitação ...
Aadaam