2015-09-09 9 views
5

mam niestandardową matcher w RSpec, że ignoruje spacje/znaki nowej linii, i po prostu pasuje do zawartości:RSpec zwyczaj diffable dopasowujący

RSpec::Matchers.define :be_matching_content do |expected| 
    match do |actual| 
    actual.gsub(/\s/,'').should == expected.gsub(/\s/,'') 
    end 

    diffable 
end 

można go używać tak:

body = " some data \n more data" 
    body.should be_matching_content("some data\nmore wrong data") 

Jednak, gdy test kończy się niepowodzeniem (jak powyższy), wyjście diff wygląda źle:

-some data 
    -more wrong data 
    + some data 
    + more data 

Czy można skonfigurować wyjście diffable ? Pierwsza linia some data ma rację, ale druga more wrong data jest nieprawidłowa. Byłoby bardzo użyteczne, aby uzyskać tylko drugą linię jako główną przyczynę niepowodzenia.

Odpowiedz

8

wierzę, należy wyłączyć Wartość domyślna diffable zachowanie w RSpec i zastąpić własną realizacji:

RSpec::Matchers.define :be_matching_content do |expected| 
    match do |actual| 
    @stripped_actual = actual.gsub(/\s/,'') 
    @stripped_expected = expected.gsub(/\s/,'') 
    expect(@stripped_actual).to eq @stripped_expected 
    end 

    failure_message do |actual| 
    message = "expected that #{@stripped_actual} would match #{@stripped_expected}" 
    message += "\nDiff:" + differ.diff_as_string(@stripped_actual, @stripped_expected) 
    message 
    end 

    def differ 
    RSpec::Support::Differ.new(
     :object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) }, 
     :color => RSpec::Matchers.configuration.color? 
    ) 
    end 
end 

RSpec.describe 'something'do 
    it 'should diff correctly' do 
    body = " some data \n more data" 
    expect(body).to be_matching_content("some data\nmore wrong data") 
    end 
end 

produkuje następujące elementy:

Failures: 

    1) something should diff correctly 
    Failure/Error: expect(body).to be_matching_content("some data\nmore wrong data") 
     expected that somedatamoredata would match somedatamorewrongdata 
     Diff: 
     @@ -1,2 +1,2 @@ 
     -somedatamorewrongdata 
     +somedatamoredata 

Można użyć niestandardowego różnią się, jeśli chcesz, nawet reimplement cały ten mechanizm dopasowywania do wywołania systemowego do komendy diff, coś takiego:

♥ diff -uw --label expected --label actual <(echo " some data \n more data") <(echo "some data\nmore wrong data") 
--- expected 
+++ actual 
@@ -1,2 +1,2 @@ 
    some data  
- more data 
+more wrong data 

Cheers!

1

Istnieje klejnot o nazwie diffy, którego można użyć.

Ale przechodzi przez linię ciągu po linii i porównuje je, więc zamiast usuwać wszystkie białe znaki, można zamienić dowolną ilość spacji na znak nowej linii i zmienić te wpisy.

To jest przykład czegoś, co można zrobić, aby nieco poprawić swoje różnice. Nie jestem w 100% pewien, gdzie umieścić ten kod w swoim kodzie.

def compare(str1, str2) 
    str1 = break_string(str1) 
    str2 = break_string(str2) 
    return true if str1 == str2 
    puts Diffy::Diff.new(str1, str2).to_s 
    return false 
end 

def break_string(str) 
    str.gsub(/\s+/,"\n") 
end 

Różne klejnoty można ustawić w celu uzyskania wyjściowego koloru odpowiedniego dla terminala.

Stosując ten kod będzie działać jak ten

str1 = 'extra some     content' 
str2 = 'extra more content' 
puts compare(str1, str2) 

byłoby wydrukować

extra 
-some # red in terminal 
+more # green in terminal 
content 
\ No newline at end of file 
4

Można zastąpić metody expected i actual, które będą następnie używane podczas generowania diff. W tym przykładzie, przechowywane i oczekiwane wartości rzeczywiste, jak i zmiennych przykład określić metodami, które zwracają zmienne przykład:

RSpec::Matchers.define :be_matching_content do |expected_raw| 
    match do |actual_raw| 
    @actual = actual_raw.gsub(/\s/,'') 
    @expected = expected_raw.gsub(/\s/,'') 
    expect(expected).to eq(@actual) 
    end 

    diffable 
    attr_reader :actual, :expected 
end 

Innym przykładem jest dopasować do konkretnych parametrów w dwóch różnych rodzajów obiektów. (Oczekiwanym obiektem w tym przypadku jest model Client.)

RSpec::Matchers.define :have_attributes_of_v1_client do |expected_client| 
    match do |actual_object| 
    @expected = client_attributes(expected_client) 
    @actual = actual_object.attributes 
    expect(actual_object).to have_attributes(@expected) 
    end 

    diffable 
    attr_reader :actual, :expected 

    def failure_message 
    "expected attributes of a V1 Client view row, but they do not match" 
    end 

    def client_attributes(client) 
    { 
     "id" => client.id, 
     "client_type" => client.client_type.name, 
     "username" => client.username, 
     "active" => client.active?, 
    } 
    end 
end 

przykład niewydolność wygląda następująco:

Failure/Error: is_expected.to have_attributes_of_v1_client(client_active_partner) 
    expected attributes of a V1 Client view row, but they do not match 
    Diff: 
    @@ -1,6 +1,6 @@ 
    "active" => true, 
    -"client_type" => #<ClientType id: 2, name: "ContentPartner">, 
    +"client_type" => "ContentPartner", 
    "id" => 11, 
+1

Uwaga: jest to podane tylko w rspec Dokumenty wyjściowych w wersji 3.4. Ponadto, zgodnie z dokumentami, nie potrzebujesz 'attr_reader' jeśli używasz' @ actual' jako nazwy zmiennej instancji. –