Domanda

Ecco quello che ho:

   context "Create ingredient from string" do
      context "1 cups butter" do

         setup do
            @ingredient = Ingredient.create(:ingredient_string => "1 cups butter")
         end

         should "return unit" do
            assert_equal @ingredient.unit, 'cups'
         end

         should "return amount" do
            assert_equal @ingredient.amount, 1.0
         end

         should "return name" do
            assert_equal @ingredient.name, 'butter'
         end
      end
      context "1 (18.25 ounce) package devil's food cake mix with pudding" do

         setup do
            @ingredient = Ingredient.create(:ingredient_string => "1 (18.25 ounce) package devil's food cake mix with pudding")
         end

         should "return unit" do
            assert_equal @ingredient.unit, '(18.25 ounce) package'
         end

         should "return amount" do
            assert_equal @ingredient.amount, 1.0
         end

         should "return name" do
            assert_equal @ingredient.name, 'devil\'s food cake mix with pudding'
         end
      end
   end

Chiaramente ci sono molte duplicazioni lì. Qualche idea su come rimuoverlo, se non altro il contesto e la stringa?

È stato utile?

Soluzione

Ecco una soluzione al tuo problema specifico. L'idea è quella di creare un metodo di classe (come il contesto, l'installazione e dovrebbe di Shoulda).

Incapsula la ripetizione in un metodo di classe accettando tutte le parti variabili come argomenti come questo:

def self.should_get_unit_amount_and_name_from_string(unit, amount, name, string_to_analyze)
  context string_to_analyze do
    setup do
      @ingredient = Ingredient.create(:ingredient_string => string_to_analyze)
    end

    should "return unit" do
       assert_equal @ingredient.unit,   unit
    end

    should "return amount" do
       assert_equal @ingredient.amount, amount
    end

    should "return name" do
       assert_equal @ingredient.name,   name
    end
  end
end

Ora puoi chiamare tutti questi test incapsulati con una linea (5 linee qui per leggibilità ;-)

context "Create ingredient from string" do
  should_get_unit_amount_and_name_from_string(
    'cups',                   
    1.0, 
    'butter', 
    "1 cups butter")
  should_get_unit_amount_and_name_from_string(
    '(18.25 ounce) package',  
    1.0, 
    'devil\'s food cake mix with pudding', 
    "1 (18.25 ounce) package devil's food cake mix with pudding")
end

In alcuni casi, potresti voler accettare un blocco che potrebbe fungere da configurazione di Shoulda.

Altri suggerimenti

La duplicazione nei test non è necessariamente una cosa negativa (tm)

Ti suggerisco di leggere i seguenti articoli da Jay Field

http://blog.jayfields.com /2007/06/testing-one-assertion-per-test.html

http: //blog.jayfields .com / 2008/05 / test-duplicate-codice-a-la-tests.html

Fanno un caso convincente per la duplicazione del codice nei test e mantengono un'asserzione per test.

I test / le specifiche non sono codici di produzione e quindi essere asciutti non è una priorità.

Il principio è che le specifiche dovrebbero essere chiare da leggere, anche se ciò significa che c'è una duplicazione del testo attraverso i test.

Non preoccuparti troppo del fatto che le specifiche siano asciutte. L'eccessiva enfasi dei test a secco tende a rendere le cose più difficili poiché devi saltare alle definizioni delle cose per capire cosa sta succedendo.

Personalmente per questo test, non avrei usato Shoulda. Puoi rimuovere facilmente la duplicazione usando la creazione dinamica del metodo come segue:

class DefineMethodTest < Test::Unit::TestCase
    [{:string => '1 cups butter', :unit => 'cups', :amount => 1.0, :name => 'butter'},{:string => '1 (18.25 ounce) package devil's food cake mix with pudding', :unit => '(18.25 ounce) package', :unit => 1.0, :name => "devil's food cake mix with pudding"}].each do |t|
        define_method "test_create_ingredient_from_string_#{t[:string].downcase.gsub(/[^a-z0-9]+/, '_')}" do
            @ingredient = Ingredient.create(:ingredient_string => t[:string])

            assert_equal @ingredient.unit, t[:unit], "Should return unit #{t[:unit]}"
            assert_equal @ingredient.amount, t[:amount], "Should return amount #{t[:amount]}"
            assert_equal @ingredient.name, t[:name], "Should return name #{t[:name]}"
        end
    end
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top