Existem estruturas de teste para desenvolvimento numérico de software

10

Descobri que boa parte da minha programação de ciências computacionais tem requisitos de teste que não são cobertos pelas estruturas de teste padrão:

  1. Teste de tempo de computação

    • Para garantir que os algoritmos não fiquem mais lentos. Eu poderia fazer algo parecido, assureSmallerEqual(RuntimeWrapper(algorithm),53)mas gostaria que o limite de 53 segundos fosse reduzido continuamente, enquanto trabalho no algoritmo, ou seja, algo comoassureSmallerEqual(RuntimeWrapper(algorithm),'previousbest+noisetolerance')
  2. Teste de performance

    • Para garantir que um algoritmo que encontrou anteriormente uma boa aproximação a uma solução analítica ainda encontre uma solução que seja pelo menos tão boa ou melhor. Novamente, isso pode ser emulado por um teste de integração padrão, mas eu gostaria que a tolerância diminuísse continuamente à medida que o algoritmo se tornasse cada vez melhor. Pense em substituir assureAlmostEqual(foo(),1,places=3)porassureAlmostEqual(foo(),1,places='previousbest')
  3. Teste de requisitos físicos

    • Para garantir que os algoritmos não precisem repentinamente de mais memória / espaço no disco rígido. Muito parecido com 1.
  4. Teste de requisitos abstratos

    • Para garantir que um algoritmo que funcionou bem com aproximações quadráticas não precise subitamente de aproximações cúbicas, ou que um algoritmo que funcionou bem com o tempo da etapa 0.1 não precise de 0,01 para estabilidade. Novamente, eles podem ser emulados por testes de integração padrão, mas o objetivo é lembrar qual foi o menor parâmetro de requisito que atingiu um determinado objetivo; portanto, isso exigiria muita atualização manual. Por exemplo, se foo(10)anteriormente não houvesse exceções, gostaria que a estrutura certificasse que foo(10)ainda funcionasse e também tentasse se foo(9)funcionasse agora (nesse caso, todos os testes futuros garantiriam que foo(9)ainda funcionem).

Alguém poderia argumentar que o que estou pedindo não descreve testes no sentido de teste de unidade / integração, já que tempos de execução maiores, por exemplo, podem ser aceitáveis ​​em troca de outras melhorias.
Na prática, no entanto, sei que economizaria muito tempo de depuração se tivesse a funcionalidade de teste acima, porque em 95% dos casos os requisitos e o desempenho foram incorretos devido a erros que introduzi. De fato, sei que muitos erros que encontrei (depois de muito tempo desperdiçado na verificação de meu próprio código) com bibliotecas de software numéricas externas poderiam ter sido evitados trivialmente se os testes acima fossem aplicados rigorosamente.

PS

A pergunta de nome semelhante /programming/34982863/framework-for-regression-testing-of-numerical-code não é uma duplicata, pois descreve a funcionalidade que é mais facilmente alcançável com estruturas de teste de regressão padrão.

A pergunta Estratégias para teste de unidade e desenvolvimento orientado a teste pede estratégias em oposição a uma estrutura que ajude a implementá-las (e as estratégias solicitadas / fornecidas nas respostas são diferentes do que descrevo aqui, na minha opinião).

Bananach
fonte
11
O software numérico é para simulação ou para análise de dados experimentais?
Mathew gunther
11
@mathewgunther Análise Numérica / Álgebra Numérica. Nenhuma análise de dados
Bananach
11
Eu sei que muitas grandes empresas de simulação usam estruturas criadas por elas mesmas. Basicamente em python. Você precisa ter casos de teste iniciados pelos scripts python e escrever alguns resultados. Posteriormente, os resultados podem ser comparados com algum tipo de referência e gerar um relatório. O teste pode ser Automized uma corrida diária ou semanal ou mensal etc. Não tenho certeza se existe algum tipo de quadro generel como software de simulação já é uma espécie de especial na implementação etc.
vydesaster

Respostas:

4

1. Esse tipo de teste parece-me mal definido porque sua condição de teste está ligada à máquina específica na qual você fez os testes em desenvolvimento. Um dos pontos de teste é que a execução dos testes no meu laptop informa se há algo errado com o código ou o ambiente que eu configurei. Os 53 segundos são específicos para sua máquina de desenvolvimento e o tempo de execução também aumentará se a máquina de teste estiver sob carga de outras cargas de trabalho ou usuários. Eu não esperaria que estruturas de teste resolvessem isso: "a função é executada na entrada em menos de 53 segundos" não é apenas uma especificação de correção muito boa.

2. Eu acho isso ambíguo e indesejável do ponto de vista dos testes de software pelas mesmas razões 1 : você perde a justificativa de aprovação ou reprovação dos testes de software.

3. Isso é bastante comum, deixe-me descrever uma solução. Não é exatamente o trabalho de uma estrutura de teste, mas você pode usar uma ferramenta separada, conforme descrito na pergunta do Unix SE, Limitar o uso de memória para um único processo Linux . Uma ferramenta padrão para tentar primeiro é o ulimitcomando in bash, que permite executar um processo e garantir que ele trava se tentar, por exemplo, alocar muita memória. Portanto, se você executar o runtestsscript com um limite de memória, ele travará e a estrutura de teste poderá lidar com isso como uma falha de teste regular.

4. A maioria dos frameworks de teste não pensam da unidade de testes desta maneira em tudo . O conjunto de testes é executado (por exemplo, antes de confirmar o código para o mestre ou antes da implantação) e o resultado é sim ou não, indicando se funciona. As estruturas de teste não consideram parte de seu trabalho, por exemplo, rastrear o progresso dos recursos, e isso não é o que geralmente é o teste. O que você faria aqui é escrever dois testes expect_succeeds(foo(10)); expect_fails(foo(9)). A cada vez, os dois testes são executados e os sucessos e as falhas esperadas passam. Quando você implementa foo(9)e é bem-sucedido, o teste de expectativa de falha agora falha, então você reescreveexpect_succeeds(foo(9)), e esse é um recurso absolutamente padrão de todas as estruturas. Mas você deve ser explícito sobre o comportamento que espera, porque, caso contrário, isso vai contra as idéias básicas dos testes de software.

AAABperforms_better(foo_A(), foo_B())BABe (b) não há mais nenhum sentido de comparar o código com o que costumava ser, todos os códigos e testes agora são imutáveis ​​e inequívocos. Isso é semelhante em espírito a como alguém pode lidar com reescritas do sistema.

Kirill
fonte