Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cuke_modeler.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
# Coveralls gem does not support any newer version than this
spec.add_development_dependency 'simplecov', '<= 0.16.1'
spec.add_development_dependency 'test-unit', '< 4.0.0'
spec.add_development_dependency 'pry', '~> 0.13.1'
end
1 change: 1 addition & 0 deletions lib/cuke_modeler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module CukeModeler
require 'cuke_modeler/named'
require 'cuke_modeler/described'
require 'cuke_modeler/stepped'
require 'cuke_modeler/fingerprint'
require 'cuke_modeler/models/model'
require 'cuke_modeler/models/feature_file'
require 'cuke_modeler/models/directory'
Expand Down
33 changes: 33 additions & 0 deletions lib/cuke_modeler/fingerprint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'digest/md5'

module CukeModeler

# NOT A PART OF THE PUBLIC API
# A mix-in module containing methods used by models that represent an element that has a name.

module Fingerprint

# NOTE: create a fingerprint for the given model using Digest::MD5
def fingerprint
# NOTE: yield the result value of the block as the argument to .hexdigest
if block_given?
value = yield self

# NOTE: The block returned nil, nothing to digest here
return nil unless value.present?

@fingerprint = Digest::MD5.hexdigest(value)

return @fingerprint
end

# NOTE: memoize fingerprint for improved performance
@fingerprint ||= begin
# NOTE: no block given, .hexdigest the to_s of the model
Digest::MD5.hexdigest(to_s)
end
end

end

end
1 change: 1 addition & 0 deletions lib/cuke_modeler/models/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Model

include Nested
include Containing
include Fingerprint


# Creates a new Model object and, if *source_text* is provided,
Expand Down
94 changes: 94 additions & 0 deletions testing/rspec/spec/integration/fingerprint_integration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
require "#{File.dirname(__FILE__)}/../spec_helper"
require 'benchmark'

describe 'Fingerprint, Integration' do

describe '.fingerprint' do

let(:model) { CukeModeler::Step.new }

before do
model.keyword = 'Given'
model.text = 'I am testing the fingerprint'
end

describe 'getting a fingerprint without args' do

it 'returns the Digest::MD5 of the to_s representation' do
expect(model.fingerprint).to eq(Digest::MD5.hexdigest(model.to_s))
end

end

describe 'getting a fingerprint with a block' do

it 'returns the Digest::MD5 of the block return value' do
fingerprint = model.fingerprint do |m|
m.text
end

expect(fingerprint).to eq(Digest::MD5.hexdigest(model.text))
end

end

describe 'getting a fingerprint with a block that returns nil' do

it 'returns nil' do
fingerprint = model.fingerprint do |m|
nil
end

expect(fingerprint).to eq(nil)
end

end

describe 'comparing fingerprints' do

let(:maximum_viable_gherkin) do
"@a_tag
#{SCENARIO_KEYWORD}: test scenario

Scenario
description

#{STEP_KEYWORD} a step
| value1 |
| value2 |
#{STEP_KEYWORD} another step
\"\"\" with content type
some text
\"\"\""
end

let(:model_one) { CukeModeler::Scenario.new(maximum_viable_gherkin) }
let(:model_two) { CukeModeler::Scenario.new(maximum_viable_gherkin) }
let(:model_three) { CukeModeler::Scenario.new }

it 'should result in the same fingerprint when classes exactly the same' do
expect(model_one.fingerprint).to eq(model_two.fingerprint)
expect(model_one.fingerprint).not_to eq(model_three.fingerprint)
end

it 'should recalculate the fingerprint when using a block' do
model_one_fingerprint = model_one.fingerprint
model_one_block_fingerprint = model_one.fingerprint { |m| m.name }

expect(model_one_fingerprint).not_to eq(model_one_block_fingerprint)
expect(model_one.fingerprint).to eq(model_one_block_fingerprint)
end

it 'is more performant than ==' do
equals_time = Benchmark.realtime { model_one == model_two }
fingerprint_time = Benchmark.realtime { model_one.fingerprint == model_two.fingerprint }

expect(equals_time > fingerprint_time).to eq(true)
end

end

end

end

2 changes: 2 additions & 0 deletions testing/rspec/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
require_relative '../../helper_methods'

require 'rubygems/mock_gem_ui'
require 'digest/md5'
require 'pry'


# Use a random dialect for testing in order to avoid hard coded language assumptions in the
Expand Down
12 changes: 12 additions & 0 deletions testing/rspec/spec/unit/fingerprint_unit_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require "#{File.dirname(__FILE__)}/../spec_helper"

describe 'Fingerprint, Unit', unit_test: true do

let(:nodule) { CukeModeler::Fingerprint }
let(:model) { Object.new.extend(nodule) }


it 'has a fingerprint' do
expect(model).to respond_to(:fingerprint)
end
end