2010-06-22 4 views
0

J'écris des tests unitaires pour l'un de mes modèles de rails. C'est un grand modèle et dans certains cas, j'ai des dizaines d'affirmations pour de nombreuses méthodes. Je préfère utiliser test/unité simple avec la syntaxe de activesupport de rails, donc j'ai un fichier comme ceci:Comment dois-je séparer les grands tests unitaires en ruby?

require 'test_helper' 
class ItemTest < ActiveSupport::TestCase 
    test "for_sale? should be true if cond 1..." 
    test "for_sale? should be true if cond 2..." 
    test "for_sale? should be true if cond 3..." 
    test "for_sale? should be true if cond 4..." 
    test "for_sale? should be false if cond 1..." 
    test "for_sale? should be false if cond 2..." 
    test "for_sale? should be false if cond 3..." 
    test "for_sale? should be false if cond 4..." 
end 

et ainsi de suite pour chacune des méthodes. Le problème est que le test devient de plus en plus compliqué car je ne peux plus compter sur setup() car le contexte de chaque groupe de tests est si différent pour chaque méthode. De plus, il est difficile de tester la méthode sur laquelle je travaille sans exécuter tous les tests.

Comment les autres gèrent-ils les grands cas de test comme celui-ci? Y a-t-il une meilleure pratique?

Répondre

1

Je recommanderais shoulda si vous voulez coller avec test/unité. Vous n'avez pas besoin d'utiliser les macros de shoulda mais cela vous donnera une fonctionnalité très utile qui s'applique ici: context. Il vous permet de diviser vos tests unitaires en sections séparées avec les leurs avant et ceux-ci peuvent être imbriqués.

context "as a really cool user" do 
    test "test number one..." 
end 

context "as a lame user" do 
    test "test number two..." 
end 

De là, vous pouvez continuer à utiliser tous les tests/syntaxe de l'unité ou si vous Shoulda gagne plus - vous pouvez changer ou mix-n match.

+0

Un autre modèle mental utile est d'utiliser 'contexte « quand une autre variable ... 'Dans l'exemple mentionné précédemment de la carte de crédit est utile de penser que:.' Contexte « lorsque la carte de crédit est volée » fais ... – Chubas

0

Je ne sais pas si c'est la meilleure pratique, mais voici ce que je fais.

Plutôt que d'avoir tous les objets que je veux jouer avec créé en setup, j'avoir des méthodes pour créer un objet spécifique, par exemple create_credit_card_already_expired, create_credit_card_stolen, create_credit_card_valid. Parfois, je mets ces méthodes dans un module, afin qu'elles puissent être partagées entre différentes classes de cas de test. Je crée également des méthodes d'assertion personnalisées, telles que assert_credit_card_rejected.

code pour exemple pour moi serait

require "test/unit" 

module TestCreditCardHelper 
    def assert_credit_card_rejected(credit_card, failure_message) 
    assert credit_card.rejected?, failure_message #A real method might be more complicated 
    end 

    def create_credit_card_stolen 
    CreditCard.new(:stolen => true) 
    end 

end 

class TestCreditCard < Test::Unit::TestCase 
    include TestCreditCardHelper 

    def test_stolen_credit_card_rejected 
    credit_card = create_credit_card_stolen 
    assert_credit_card_rejected(credit_card, "Doesn't reject stolen credit cards") 
    end 
end 
0

Un test unitaire doit tester une seule chose. Cela semble trop est testé ici. Il devrait y avoir un test par condition.

require 'test_helper' 
class ItemTest_Condition1 < ActiveSupport::TestCase 
    test "for_sale? should be true if cond 1..." 
    test "for_sale? should be false if cond 1..." 
end 

class ItemTest_Condition2 < ActiveSupport::TestCase 
    test "for_sale? should be true if cond 2..." 
    test "for_sale? should be false if cond 2..." 
end 
class ItemTest_Condition3 < ActiveSupport::TestCase 
    test "for_sale? should be true if cond 3..." 
    test "for_sale? should be false if cond 3..." 
end 
...