Quais são as melhores práticas para testar módulos no rspec? Eu tenho alguns módulos que são incluídos em alguns modelos e, por enquanto, eu simplesmente tenho testes duplicados para cada modelo (com poucas diferenças). Existe uma maneira de secar?
ruby
unit-testing
rspec
Andrius
fonte
fonte
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
dessa maneira, obtenho a variável de instância mais usada para testar de qualquer maneira.include
não funciona para mim, masextend
fazlet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
O que Mike disse. Aqui está um exemplo trivial:
código do módulo ...
fragmento de especificação ...
fonte
include Say
dentro da declaração DummyClass em vez de ligarextend
?extend
a instância da classe, ou seja, depois denew
ter sido chamado. Se você estava fazendo isso antesnew
é chamado então você está certo você usariainclude
DummyClass
constante? Por que não apenas@dummy_class = Class.new
? Agora você está poluindo seu ambiente de teste com uma definição de classe desnecessária. Este DummyClass é definido para todas e cada uma de suas especificações e, na próxima especificação, onde você decide usar a mesma abordagem e reabrir a definição de DummyClass, ela já pode conter algo (embora neste exemplo trivial a definição seja estritamente vazia, na vida real casos de uso é provável que algo é adicionado em algum momento e, em seguida, esta abordagem torna-se perigoso).Para módulos que podem ser testados isoladamente ou zombando da classe, eu gosto de algo como:
módulo:
especificação:
Pode parecer errado seqüestrar grupos de exemplos aninhados, mas eu gosto da concisão. Alguma ideia?
fonte
let
método descrito por @metakungfu é melhor.Encontrei uma solução melhor na página inicial do rspec. Aparentemente, ele suporta grupos de exemplos compartilhados. Em https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
fonte
Em primeiro lugar, você poderia criar uma classe fictícia em seu script de teste e incluir o módulo nisso? Em seguida, teste se a classe dummy tem o comportamento da maneira que você esperaria.
EDIT: Se, como apontado nos comentários, o módulo espera que alguns comportamentos estejam presentes na classe em que ele é misturado, tentarei implementar manequins desses comportamentos. Apenas o suficiente para deixar o módulo feliz em desempenhar suas funções.
Dito isso, eu ficaria um pouco nervoso com meu design quando um módulo espera muito da classe host (dizemos "host"?) - Se eu ainda não herdar de uma classe base ou não puder injetar a nova funcionalidade na árvore de herança, acho que tentaria minimizar quaisquer expectativas que um módulo possa ter. Minha preocupação é que meu design comece a desenvolver algumas áreas de inflexibilidade desagradável.
fonte
A resposta aceita é a resposta certa, no entanto, eu queria adicionar um exemplo de como usar rpsecs
shared_examples_for
eit_behaves_like
métodos. Menciono alguns truques no trecho de código, mas para obter mais informações, consulte este relishapp-rspec-guide .Com isso, você pode testar seu módulo em qualquer uma das classes que o incluem. Então você realmente está testando o que usa em seu aplicativo.
Vamos ver um exemplo:
Agora vamos criar especificações para o nosso módulo:
movable_spec.rb
fonte
A respeito:
fonte
Eu sugeriria que, para os módulos maiores e mais utilizados, você deveria optar pelos "Grupos de Exemplos Compartilhados", conforme sugerido por @Andrius aqui . Para coisas simples para as quais você não deseja passar pelo problema de ter vários arquivos, etc., veja como garantir o máximo controle sobre a visibilidade de suas coisas falsas (testado com o rspec 2.14.6, basta copiar e colar o código em um arquivo arquivo spec e execute-o):
fonte
subject { dummy_class.new }
está funcionando. O caso comsubject { dummy_class }
não está funcionando para mim.meu trabalho recente, usando o mínimo de fiação possível
Eu gostaria
funcionou, mas não funciona (como no Ruby MRI 2.2.3 e no RSpec :: Core 3.3.0)
Obviamente, a classe_descrita não é visível nesse escopo.
fonte
Para testar seu módulo, use:
Para secar algumas coisas que você usa em várias especificações, você pode usar um contexto compartilhado:
Recursos:
fonte
Você também pode usar o tipo auxiliar
Aqui está a documentação: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
fonte
você precisa simplesmente incluir seu módulo no seu arquivo de especificação
mudule Test module MyModule def test 'test' end end end
no seu arquivo de especificaçãoRSpec.describe Test::MyModule do include Test::MyModule #you can call directly the method *test* it 'returns test' do expect(test).to eql('test') end end
fonte
Uma solução possível para testar o método do módulo, independente da classe que os incluirá
E especifique isso
E se você quiser testá-los, o shared_examples é uma boa abordagem
fonte
subject(:module_to_test_instance) { Class.new.include(described_class) }
. Caso contrário, não vejo nada de errado com sua resposta.Esse é um padrão recorrente, pois você precisará testar mais de um módulo. Por esse motivo, é mais do que desejável criar um auxiliar para isso.
Encontrei este post que explica como fazê-lo, mas estou lidando aqui, pois o site pode ser desativado em algum momento.
Isso é para evitar que as instâncias do objeto não implementem o método da instância:: qualquer erro que você receber ao tentar
allow
métodos nodummy
classe.Código:
No
spec/support/helpers/dummy_class_helpers.rb
No
spec/spec_helper.rb
Nas suas especificações:
fonte