2009-02-19 6 views
3

Si vous écrivez une classe de test commedes méthodes Détection écrasement de test rubis

class MyTest < Test::Unit::TestCase 
    def setup 
    end 

    def test_1 
    flunk 
    end 

    def test_1 
    assert true 
    end 
end 

la première test_1 est ignorée. Bien que cela ressemble à une erreur stupide, cela peut arriver avec la programmation copier-coller. En dehors de l'exécution

grep test test_me.rb | wc 

et en le comparant avec le nombre unité d'essai des tests Says a été exécuté, ou en utilisant rcov ou chahuter, ou en cours d'exécution avec -w, comment pouvez-vous détecter ces problèmes?

De même, existe-t-il un moyen de spécifier que les méthodes de test ne doivent pas être remplacées?

Modifier: La méthode testée possédait un paramètre avec 6 valeurs possibles et le testeur voulait tester chaque scénario. C'est pourquoi la programmation copier-coller a été utilisée. La seule alternative que je peux envisager pour un tel scénario est un tableau à six éléments de paramètres et de valeurs attendues.

Répondre

5

Vous pouvez profiter de method_added de Ruby qui est appelée à chaque fois qu'une méthode est ajoutée à une classe. Vous devriez être capable de faire quelque chose dans un module que vous incluez, mais voici un exemple simple de le faire dans votre classe de test.

class MyTest < Test::Unit::TestCase 

    @@my_tests = [] 

    def self.method_added(sym) 
    raise "#{sym} already defined!" if @@my_tests.include? sym 
    @my_tests << sym 
    end 

    def test_foo_1 
    end 

    def test_foo_2 
    end 

    def test_foo_1 
    end 
end 
+0

Bien que ce soit utile (j'ai fait upvote), je ne pense pas que cela devrait être la réponse acceptée. La bonne chose à faire n'est pas copier et coller, ne pas valider le copier-coller. – DanSingerman

+0

Tout le monde peut dire "Ne pas copier et coller" - comme on dit, donner de bons conseils est facile, suivre c'est la partie la plus difficile. J'apprécie les réponses qui me disent quelque chose que je ne connais pas. –

1

Est-ce vraiment un problème si vous donnez à vos tests des noms descriptifs appropriés? Voici un exemple de certains noms de méthode de test de mon projet le plus récent:

test_should_not_do_html_escaping_for_administrators 
test_should_not_be_able_to_create_project_with_company_user_doesnt_own 
test_should_be_able_to_edit_own_projects 
test_should_not_be_able_to_edit_others_projects 

Si vos noms de tests sont assez courts que vous pouvez facilement écraser ou les dupliquer, vous n'êtes probablement pas être suffisamment descriptif de ce que vous » re tester réellement dans chacun.

+0

La méthode testée avait six possibilités (1 à 6) pour l'un des paramètres, et les tests étaient test_foo_1 à tester_foo_6 pour tester chacune de ces possibilités (sauf qu'il y avait deux test_foo_5 et pas de test_foo_6). Auriez-vous utilisé un tableau de 1 à 6 à la place? –

+0

Gardez votre test aussi simple que possible. L'idée du test est de rendre la conception de votre code meilleure. Le développeur suivant qui viendra et maintiendra le projet devrait être capable de regarder votre test et voir ce qu'il fait. – andHapp

0

Évitez la programmation Copier-Coller. Rejeter les raccourcis clavier si vous le devez.

2

Edit: La méthode testée avait un paramètre avec 6 ou si valeurs possibles, et le testeur a voulu tester chaque scénario. C'est la raison pour laquelle la programmation de copier et de coller a été utilisée.

Dans ces circonstances, je fais ceci:

def test_foo 
    test_cases = [ 
    {:param => 1, :expected => 'whatever is expected'}, 
    {:param => 2, :expected => 'whatever is expected'}, 
    {:param => 3, :expected => 'whatever is expected'}, 
    {:param => 4, :expected => 'whatever is expected'}, 
    {:param => 5, :expected => 'whatever is expected'}, 
    {:param => 6, :expected => 'whatever is expected'} 
    ] 

    for test_case in test_cases 
    do_the_test(test_case) 
    end 
end 

def do_the_test(test_case) 
    # test code here 
end 

Cela évite complètement copier et coller, qui, comme on l'a dit, est mauvais

La seule alternative que je peux envisager un tel un scénario est un tableau à six éléments de paramètres et valeurs attendues.

Exactement!

+0

C'est l'approche que j'aurais moi-même adoptée. Je suppose que je ne voulais pas être trop critique de l'auteur des tests, et introduire une boucle dans un test peut être inhabituel pour certains. –

2

En ce qui concerne la réponse de HermanD, puisqu'il s'agit de Ruby!, Vous pouvez aussi le faire directement dans la classe pour créer des méthodes de test uniques:

class MyObjectTest < Test::Unit::TestCase 
    [ 
    {:param => 1, :expected => 'whatever is expected'}, 
    {:param => 2, :expected => 'whatever is expected'}, 
    {:param => 3, :expected => 'whatever is expected'}, 
    {:param => 4, :expected => 'whatever is expected'}, 
    {:param => 5, :expected => 'whatever is expected'}, 
    {:param => 6, :expected => 'whatever is expected'} 
    ].each do |test_case| 
    define_method :"test_using_#{test_case[:param]}_should_return_#{params[:expected].underscore}" do 
     assert_equal test_case[:expected], MyObject.new.do_something_with(test_case[:param]) 
    end 
    end 
end 

Il se sent encore plus naturel en utilisant la phrase de Rspec (ou de Shoulda) comme langue:

describe MyObject do 
    [ 
    {:param => 1, :expected => 'whatever is expected'}, 
    {:param => 2, :expected => 'whatever is expected'}, 
    {:param => 3, :expected => 'whatever is expected'}, 
    {:param => 4, :expected => 'whatever is expected'}, 
    {:param => 5, :expected => 'whatever is expected'}, 
    {:param => 6, :expected => 'whatever is expected'} 
    ].each do |test_case| 
    it "should return #{test_case[:expected]} when using #{test_case[:param]}" do 
     MyObject.new.do_something_with(test_case[:param]).should == test_case[:expected] 
    end 
    end 
end 
0

La version bijou d'essai -unit a la capacité de détecter la redéfinition du test à partir de 2.0.7.

Questions connexes