Quelles sont les meilleures pratiques pour tester les modules dans rspec? J'ai quelques modules qui sont inclus dans quelques modèles et pour l'instant j'ai simplement des tests en double pour chaque modèle (avec quelques différences). Y a-t-il un moyen de le SÉCHER?
ruby
unit-testing
rspec
Andrius
la source
la source
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
cette façon, j'obtiens la variable d'instance qui est le plus souvent utilisée pour tester de toute façon.include
ne fonctionne pas pour moi mais leextend
faitlet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
Ce que Mike a dit. Voici un exemple trivial:
code du module ...
fragment de spécification ...
la source
include Say
dans la déclaration DummyClass au lieu d'appelerextend
?extend
dans l'instance de la classe, c'est-à-dire aprèsnew
avoir été appelé. Si vous faisiez cela avantnew
est appelé, vous avez raison, vous utiliseriezinclude
DummyClass
constante? Pourquoi pas juste@dummy_class = Class.new
? Maintenant, votre environnement de test pollue avec une définition de classe inutile. Cette DummyClass est définie pour chacune de vos spécifications et dans la spécification suivante où vous décidez d'utiliser la même approche et de rouvrir la définition DummyClass, elle peut déjà contenir quelque chose (bien que dans cet exemple trivial, la définition soit strictement vide, dans la vraie vie cas d'utilisation, il est probable que quelque chose soit ajouté à un moment donné, puis cette approche devient dangereuse.)Pour les modules qui peuvent être testés isolément ou en se moquant de la classe, j'aime quelque chose du genre:
module:
spec:
Il peut sembler incorrect de détourner des groupes d'exemples imbriqués, mais j'aime la concision. Des pensées?
la source
let
méthode décrite par @metakungfu est meilleure.J'ai trouvé une meilleure solution sur la page d'accueil de rspec. Apparemment, il prend en charge les groupes d'exemples partagés. De https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
la source
Pourriez-vous créer une classe factice dans votre script de test et y inclure le module? Vérifiez ensuite que la classe factice a le comportement que vous attendez.
EDIT: Si, comme indiqué dans les commentaires, le module s'attend à ce que certains comportements soient présents dans la classe dans laquelle il est mélangé, alors j'essaierais d'implémenter des mannequins de ces comportements. Juste assez pour que le module soit heureux d'accomplir ses tâches.
Cela dit, je serais un peu nerveux à propos de ma conception lorsqu'un module attend beaucoup de sa classe hôte (disons-nous "hôte"?) - Si je n'hérite pas déjà d'une classe de base ou si je ne peux pas injecter la nouvelle fonctionnalité dans l'arborescence d'héritage alors je pense que j'essaierais de minimiser les attentes de ce type qu'un module pourrait avoir. Ma préoccupation étant que ma conception commence à développer des zones d'inflexibilité désagréable.
la source
La réponse acceptée est la bonne réponse, je pense, mais je voulais ajouter un exemple sur la façon d'utiliser les rpsecs
shared_examples_for
et lesit_behaves_like
méthodes. Je mentionne quelques astuces dans l'extrait de code, mais pour plus d'informations, consultez ce relishapp-rspec-guide .Avec cela, vous pouvez tester votre module dans l'une des classes qui l'incluent. Vous testez donc vraiment ce que vous utilisez dans votre application.
Voyons un exemple:
Créons maintenant les spécifications de notre module:
movable_spec.rb
la source
Qu'en est-il de:
la source
Je suggérerais que pour les modules plus grands et très utilisés, optez pour les "Groupes d'exemples partagés" comme suggéré par @Andrius ici . Pour les trucs simples pour lesquels vous ne voulez pas avoir la peine d'avoir plusieurs fichiers, etc. voici comment assurer un contrôle maximal sur la visibilité de vos trucs factices (testé avec rspec 2.14.6, copiez et collez simplement le code dans un spec et exécutez-le):
la source
subject { dummy_class.new }
fonctionne. Le cas avecsubject { dummy_class }
ne fonctionne pas pour moi.mon travail récent, en utilisant le moins de câblage possible
je souhaite que
a fonctionné, mais ce n'est pas le cas (comme à Ruby MRI 2.2.3 et RSpec :: Core 3.3.0)
La description_class n'est évidemment pas visible dans cette étendue.
la source
Pour tester votre module, utilisez:
Pour SÉCHER certaines choses que vous utilisez sur plusieurs spécifications, vous pouvez utiliser un contexte partagé:
Ressources:
la source
Vous pouvez également utiliser le type d'assistance
Voici la documentation: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
la source
vous devez simplement inclure votre module dans votre fichier de spécifications
mudule Test module MyModule def test 'test' end end end
dans votre fichier de spécificationsRSpec.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
la source
Une solution possible pour tester la méthode des modules qui sont indépendants de la classe qui les inclura
Et spec pour ça
Et si vous voulez les tester à sec , alors shared_examples est une bonne approche
la source
subject(:module_to_test_instance) { Class.new.include(described_class) }
. Sinon, je ne vois vraiment rien de mal à votre réponse.Il s'agit d'un modèle récurrent car vous allez devoir tester plus d'un module. Pour cette raison, il est plus que souhaitable de créer une aide pour cela.
J'ai trouvé ce post qui explique comment le faire, mais je me débrouille ici car le site pourrait être supprimé à un moment donné.
C'est pour éviter que les instances d'objet n'implémentent la méthode d'instance:: quelle que soit l' erreur que vous obtenez lorsque vous essayez d'
allow
utiliser des méthodes sur ladummy
classe.Code:
Dans
spec/support/helpers/dummy_class_helpers.rb
Dans
spec/spec_helper.rb
Dans vos spécifications:
la source