Faço parte de um grupo de desenvolvimento com 5 equipes, totalizando cerca de 40 desenvolvedores. Estamos seguindo a metodologia Scrum, com sprints de 3 semanas. Temos uma configuração de integração contínua (Jenkins), com um pipeline de construção que leva várias horas (devido a extensos testes automatizados). Basicamente, o processo de desenvolvimento funciona bem.
No entanto, observamos que, depois de alguns dias em um novo sprint, nossa compilação geralmente fica instável e permanece instável até o final do sprint "parar de confirmar". O efeito adverso disso é que as etapas de compilação estão muito abaixo do pipeline, especialmente os testes de interface do usuário / Web não são executados por vários dias (porque são acionados apenas em uma compilação 'verde'). Consequentemente, os erros recém-introduzidos geralmente são detectados apenas muito tarde no sprint.
- Cada confirmação é verificada em relação a um conjunto básico de testes. Uma vez verificada, a alteração é enviada para mestre após uma revisão de código (Gerrit)
- Os testes básicos de unidade são executados a cada 30 minutos, duração inferior a 10 minutos
- Os testes de integração são executados a cada 2h, duração 1h
- Os testes de interface do usuário / Web são executados em testes de integração bem-sucedidos, com duração de várias horas
Dependendo de quem é responsável pela estabilidade da compilação durante o sprint (essa responsabilidade é repassada por cada sprint), pode haver "paradas de confirmação" ad-hoc intermediárias para que a compilação volte a ficar estável.
Então, nós queremos:
- Nossas equipes de desenvolvimento desenvolvem e cometem alterações durante um sprint sem obstáculos
- Nosso processo de construção é abandonado se uma etapa da construção falhar, pois os resultados subsequentes da construção têm pouco significado
- Nosso processo de criação para fornecer aos desenvolvedores um feedback de qualidade em tempo hábil
Dado (2), os pontos (1) e (3) parecem contradizer-se. Alguém tem uma boa prática de como lidar com isso?
( No momento, estamos perdendo o ponto (2) e permitindo a continuação da compilação, mesmo em etapas com falha na compilação. Ainda não tenho nenhum comentário sobre como isso influencia nossa qualidade )
Obrigado Simon
fonte
several hours
, esse é o verdadeiro problema. significa que a solução combinada é muito grande e muito ampla. Você deve procurar componenteizar a solução e, em seguida, ter pequenos blocos de código como pacotes (disponíveis de uma maneira ou de outra nos principais idiomas de todas as plataformas). Portanto, quaisquer alterações serão inseridas apenas nos componentes e serão detectadas muito mais rapidamente. A compilação completa basicamente unirá os componentes já combinados e também será mais rápida. Você só executaria possivelmente alguns testes para garantir que os componentes certos fossem resolvidos.Respostas:
Alguns princípios básicos primeiro: - As principais alterações devem sempre estar em uma ramificação do recurso no seu VCS - As ramificações do recurso devem passar em todos os testes antes de mesclar no tronco. Adicionado - Confirmações sempre devem ser construídas - Uma compilação interrompida requer ação imediata do responsável pela comunicação e / ou do restante da equipe. - Um teste com falha só deve abortar os testes restantes se for um teste crítico .
Se você, como uma equipe, seguir essas práticas e aplicá-las, por exemplo: "nome e vergonha" quando a compilação for interrompida, você deve seguir em frente, pois quaisquer confirmações que possam interromper a compilação estarão em um ramo de recurso. Outras confirmações que quebram a compilação terão que ser tratadas imediatamente e você obterá os resultados dos testes posteriores.
Você também pode adicionar um teste automático da última compilação "bem-sucedida" (não necessariamente a que passa nos testes de integração), para os testes de interface do usuário / Web como uma execução noturna, relatando a primeira coisa da manhã.
fonte
Não tem nada a ver com Scrum. Sua construção deve ser continuamente estável, independentemente.
Ninguém deve fazer check-in, a menos que tenha realizado uma construção local e executado os testes de unidade localmente (e ambos foram aprovados, é claro). O processo local de criação e teste deve ser sensível a modificações e pode ignorar os testes de código que não foi alterado.
Qualquer pessoa que introduza algo que causa falha na compilação ou falha em um teste de unidade deve ser publicamente envergonhada . Se a construção for interrompida, ela deverá ser corrigida imediatamente.
fonte
Seu problema parece ser que os testes demoram muito para serem executados. Felizmente, a lei de Moore nos forneceu uma solução para esse problema. Hoje, as CPUs de servidor high-end podem facilmente ter mais de 10 núcleos (e mais de 10 HyperThreads). Pode haver várias dessas CPUs em um único computador.
Se eu tivesse testes que demorassem tanto tempo, resolveria o problema com mais hardware. Eu compraria um servidor high-end e, em seguida, paralelizaria os testes para que eles tirassem vantagem total de todos os núcleos da CPU. Atualmente, se seus testes são de thread único, aproveitar 10 núcleos e 10 HyperThreds provavelmente torna os testes 15 vezes mais rápidos. Obviamente, isso significa que eles também usam 15 vezes a memória, portanto o computador precisa ter RAM suficiente.
Assim, as várias horas se transformarão em 10 a 30 minutos.
Você não disse quanto tempo a compilação leva, mas ferramentas de compilação padrão como make permitem paralelizar também a compilação. Se você paralelizar seus testes de unidade e o computador desenvolvedor típico tiver 4 núcleos e 4 HyperThreads, menos de 10 minutos de testes de unidade se transformarão em menos de 2 minutos. Então, talvez você possa aplicar uma política em que todos devem executar os testes de unidade antes de cometer?
Sobre a falha no teste para interromper outros testes: não faça isso no servidor de construção! Você deseja o máximo de informações possível sobre a falha e outros testes podem revelar algo importante. Obviamente, se a construção falhar, você não poderá executar testes de unidade. Se o desenvolvedor executar testes de unidade em sua própria máquina, convém abortar na primeira falha.
Não vejo nenhuma conexão entre o Scrum e seus problemas. Os problemas podem realmente ocorrer com qualquer processo de desenvolvimento.
fonte
Não é possível ter mais instalações do Jenkins e fazer com que os desenvolvedores verifiquem uma instância separada do Jenkins?
Eu acho que a melhor solução aqui é fazer com que o código passe em todos os testes antes de ser verificado no ramo mestre e compilado / testado pela instância principal do Jenkins. Não permita que as pessoas façam check-in do código que quebra a compilação.
Verifico meu código no ramo de desenvolvimento, vejo se ele passa nos testes e crio uma solicitação de recebimento. Mas você poderia obviamente fazer com que Jenkins puxasse um ramo de recursos e teste esse.
fonte
O ponto (2) parece ser o ponto mais doloroso, por isso vou me concentrar nisso.
Talvez seja hora de dividir o projeto em vários módulos.
https://en.wikipedia.org/wiki/Dependency_inversion_principle
Se um módulo falhar na construção, a construção para outros módulos poderá continuar, desde que esses outros módulos possam depender de uma interface e o código que compõe essa interface tenha sido construído com êxito.
Isso fornecerá feedback sobre quais outras falhas de compilação podem ocorrer, para que você tenha tempo para corrigir mais de um módulo quebrado antes que a próxima compilação aconteça.
Em geral, os princípios do SOLID são concebidos para lidar com bibliotecas e criar problemas. Em outras palavras - esse conjunto de princípios é concebido para resolver o tipo exato de problemas que você está enfrentando.
Como uma observação lateral (veja a resposta do juhist), você não pode fazer a compilação rodar mais rápido (por paralelismo) se não particionar a compilação em módulos separados.
fonte
Acho que sua equipe está perdendo um dos principais princípios do scrum: pronto, software funcionando. Um PBI não deve ser marcado como concluído até que seja aprovado na Definição de Concluído que sua equipe estabeleceu. A definição de Concluído é diferente para cada equipe, mas provavelmente incluiria coisas como:
Então, essencialmente, o que está acontecendo é que sua equipe está marcando coisas que de fato não são feitas. Isso é um problema por si só.
Fora isso, tudo se resume ao gerenciamento de controle de versão adequado. Se você estiver usando o Git, todo o trabalho será feito no repositório local do desenvolvedor e eles não deverão enviar nada para o remoto, a menos que esteja "pronto" e potencialmente liberável. Trabalho incompleto nunca deve ser enviado ao seu repositório principal. Se o desenvolvedor precisar trabalhar em um ramo de recursos de vida útil mais longa e quiser ir para o remoto para garantir que eles não percam o trabalho, eles devem trabalhar com um garfo e, em seguida, você o mesclará no principal quando o O recurso está "pronto" e potencialmente liberável - não antes.
Para TFVC, é um pouco mais complicado porque tudo acontece no "remoto". Isso significa que os desenvolvedores devem, portanto, sempre trabalhar com ramificações, a menos que seja uma solução rápida. As mesmas regras se aplicam aqui como no Git, no entanto: software incompleto não é comprometido. Período. No controle de versão gerenciado corretamente, "main" deve sempre ser liberável. Se um commit foi feito desse modo "principal", você não está fazendo o certo.
fonte