Por que as estruturas xUnit não permitem que os testes sejam executados em paralelo?

15

Você conhece alguma estrutura do xUnit que permite executar testes em paralelo, para usar vários núcleos na máquina atual?

Se nenhum (ou tão poucos) faz isso, talvez haja uma razão ... Será que os testes geralmente são tão rápidos que as pessoas simplesmente não sentem a necessidade de paralelizá-los?

Existe algo mais profundo que impeça a distribuição (pelo menos alguns) dos testes em vários threads?

Xavier Nodet
fonte
O teste de unidade é definitivamente lento. Mesmo que cada teste por si só seja rápido, eles acumularão, pois as pessoas literalmente têm milhões de casos de teste.
Pacerier 31/08/2015

Respostas:

6

O NUnit 2.5 empacotou o pNUnit que permite a execução de testes em paralelo.

Esta versão inclui o pNUnit, um corredor NUnit estendido para testes paralelos distribuídos. O programa pNUnit foi desenvolvido na Codice Software para uso no teste do Plastic SCM e foi contribuído para o NUnit. Para obter mais informações sobre o uso do pNUnit, consulte o site do pNUnit.

O lado JUnit tem junção paralela e também amino .

Aaron McIver
fonte
Portanto, a única razão para as outras estruturas seria 'ainda não implementada'?
Xavier Nodet
1
@Xavier Sim; essa é uma afirmação justa.
Aaron McIver
10

Para responder à segunda parte da sua pergunta: Existe algo mais profundo que impede a distribuição (pelo menos alguns) dos testes em vários segmentos?

Uma grande quantidade de código funciona apenas quando executada em thread único. É trivial produzir acidentalmente contenção de recursos e bloqueios ao gravar programas com a suposição de que eles serão executados em um único encadeamento. E isso funciona bem porque a maioria dos programas realmente executa um thread único. O paralelismo é obtido com a execução de várias cópias ou programas diferentes ao mesmo tempo (scripts da web sendo um exemplo comum - muitos usuários acessando uma única página significa muitas cópias dos scripts dessa página em execução ao mesmo tempo).

Imagine uma classe simples "log para arquivo". Quando você cria uma instância, ele abre o arquivo para gravação; quando você libera a instância, ele fecha o arquivo. Portanto, o primeiro teste cria uma instância e começa a executar um teste. O segundo teste faz a mesma coisa em um segundo thread. E falha, porque a segunda instância não pode obter acesso de gravação ao arquivo. Mas se fosse executado um de cada vez, todos os testes passariam.

Tudo isso pode ser codificado e o exemplo simples pode ser ajustado para funcionar. Mas fazer isso provavelmente não é necessário para o programa original . Ter que escrever um código de thread-safe para que você possa executar testes de unidade não é razoável para muitas pessoas. Portanto, os testes de unidade multithread devem permanecer um extra opcional.


fonte
+1 Esta deve ser a resposta excetuada, porque na verdade responde ao porquê.
23713 Oliver Weiler
4

Se os testes precisarem configurar e consultar um banco de dados, os testes em paralelo interfeririam entre si, a menos que haja um banco de dados separado para cada teste em paralelo.

Clint Miller
fonte
Não é para a plataforma de teste (xUnit) se preocupar; esse é um detalhe de implementação.
Aaron McIver
E nem todos os testes escritos em uma estrutura de teste de unidade são testes de unidade, assim como o que acessa o banco de dados não é realmente um teste de unidade, mais como um teste de integração.
c_maker
Só porque um teste toca um banco de dados não significa que é um teste de integração. Um método que é executado parcialmente em C # e parcialmente em um sproc de banco de dados, por exemplo, ainda é conceitualmente um teste de unidade, desde que nenhuma pré-configuração seja esperada (ou seja, o esquema de dados esteja presente, mas nenhum dado esteja presente). Esses testes podem criar dados para uma execução individual, mas devem redefinir para um estado em branco quando terminar). Essa é provavelmente uma opinião controversa, mas esses testes não podem ser considerados testes de integração, porque são explicitamente testes de configuração zero e implantação zero que testam pequenas unidades de código.
Triynko 13/12/19
2

Embora o JUnit por si só possa não permitir isso (embora eu não esteja intimamente familiarizado com suas versões mais recentes), o Maven com seu plug-in Surefire tem uma opção para executar testes em paralelo. Ainda não tentei ainda.

Não sou fortemente pressionado a investigar essa opção, pois temos pouco mais de mil testes e eles são executados com rapidez suficiente. No entanto, eu sei que alguns dos equipamentos de teste têm dependências implícitas entre (encontramos algumas dessas dependências quando alguns testes foram interrompidos inesperadamente no passado), então há um risco de que paralelizar os testes faça com que alguns deles falhem imprevisivelmente. Você pode dizer que está tudo bem, pois torna o problema explícito. No entanto, estamos lidando com um sistema legado e temos muitas questões mais importantes para lidar - o tempo é um recurso escasso (como sempre).

Péter Török
fonte
0

A codificação multithread não é trivial. Mesmo quando feito por pessoas que sabem o que estão fazendo, podem ocorrer erros dependentes do tempo. Eles são difíceis de corrigir. Tendo lidado com alguns milhares de erros de tipo de caso que a multi-trilha pode produzir, eu preferiria não tê-los em minha estrutura de teste. A primeira correção que recebi parecia funcionar, mas em testes posteriores, verificou-se que havia se tornado um bug de dezenas em milhares.

As técnicas para executar multi-threading em multiprocessadores estão melhorando com o advento dos PCs multiprocessadores. No entanto, levará algum tempo até que eles sejam amplamente utilizados.

Alguns conjuntos de testes têm dependências entre testes que não precisam ser explicitamente declarados quando os testes são executados em um único fluxo. No entanto, em um mecanismo com vários vapores, eles precisariam ser explicitamente declarados. (Onde essas dependências devem existir é uma questão diferente.)

De outro ponto de vista, algumas coisas simplesmente não precisam ser executadas em paralelo. Se o processo for executado de maneira adequada, pode ser melhor concentrar esforços em outras coisas além de implementar o multiencadeamento.

BillThor
fonte
0

O MBUnit é capaz de executar testes em paralelo simplesmente especificando alguns atributos de nível de montagem.

[assembly: DegreeOfParallelism(6)]
[assembly: Parallelizable(TestScope.All)]

Eu tenho usado esse projeto para executar testes de selênio em paralelo com bastante sucesso por algum tempo. Infelizmente, o projeto não está mais vivo.

O xUnit 2.0 também deve suportar testes de unidade paralelos, mas ainda não o testei.

Ivo Grootjes
fonte