gatling 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -9,3 +9,5 @@ test*
9
9
  .DS_Store
10
10
  spec/support/ready_candidate_ref/temp/*
11
11
  reports/*
12
+ vendor/*
13
+
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p125
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@gatling --create
data/Gemfile CHANGED
@@ -4,9 +4,7 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :development, :test, :smoke do
7
- gem 'sinatra' ,'1.3.1'
8
- gem 'rack-test'
9
- gem 'rake'
10
- gem 'rspec-instafail'
11
- gem 'pry'
7
+ gem 'rake'
8
+ gem 'rspec-instafail'
9
+ gem 'pry'
12
10
  end
data/lib/gatling.rb CHANGED
@@ -1,88 +1,74 @@
1
+ #Dir["/gatling/*.rb"].each {|file| require file}
2
+
1
3
  require 'RMagick'
2
- require_relative 'gatling/capture_element'
3
4
  require 'capybara'
4
5
  require 'capybara/dsl'
5
- require 'gatling/config'
6
-
7
-
8
- module Gatling
9
- class Comparison
10
- include Capybara::DSL
11
-
12
- #TODO: Training mode
13
- #TODO: Diff with reports
14
- #TODO: Fuzz matches
15
- #TODO: Helpers for cucumber
16
6
 
17
- def initialize expected, actual
18
- @expected = expected
19
- @actual = actual
20
-
21
- @capture_element = Gatling::CaptureElement.new(@actual)
7
+ require 'gatling/config'
8
+ require 'gatling/file_helper'
9
+ require 'gatling/image'
10
+ require 'gatling/comparison'
11
+ require 'gatling/capture_element'
22
12
 
13
+ # include Gatling::Comparison
23
14
 
24
- @reference_image_path = Gatling::Configuration.reference_image_path
25
- @trainer_toggle = Gatling::Configuration.trainer_toggle
15
+ #TODO: Fuzz matches
16
+ #TODO: Helpers for cucumber
17
+ #TODO: Make directories as needed
26
18
 
27
- @expected_image = "#{@reference_image_path}/#{@expected}"
28
- @expected_filename = "#{@expected}".sub(/\.[a-z]*/,'')
29
- end
19
+ module Gatling
30
20
 
31
- def create_diff
32
- diff_path = "#{@reference_image_path}/diff"
21
+ class << self
33
22
 
34
- FileUtils::mkdir_p(diff_path)
23
+ def matches?(expected_reference_filename, actual_element)
35
24
 
36
- @diff_metric.first.write("#{diff_path}/#{@expected_filename}_diff.png")
25
+ Gatling::FileHelper.make_required_directories
37
26
 
38
- candidate = save_element_as_candidate(@cropped_element)
39
- raise "element did not match #{@expected}. A diff image: #{@expected_filename}_diff.png was created in #{diff_path}. A new reference #{candidate} can be used to fix the test"
40
- end
27
+ expected_reference_file = (File.join(Gatling::Configuration.paths[:reference], expected_reference_filename))
28
+ actual_image = Gatling::Image.new(:from_element, expected_reference_filename, actual_element)
41
29
 
42
- def save_element_as_candidate(element)
43
- candidate_path = "#{@reference_image_path}/candidate"
44
- candidate = @capture_element.save_element(element, @expected_filename, candidate_path)
30
+ if Gatling::Configuration.trainer_toggle
31
+ save_image_as_reference(actual_image)
32
+ return true
45
33
  end
46
34
 
47
- def save_element_as_reference(element)
48
- if File.exists?(@expected_image) == false
49
- @capture_element.save_element(element, @expected_filename, @reference_image_path)
50
- puts "Saved #{@expected_image} as reference"
51
- else
52
- puts "#{@expected_image.upcase} ALREADY EXISTS. REFERENCE IMAGE WAS NOT OVERWRITTEN. PLEASE DELETE THE OLD FILE TO UPDATE USING TRAINER"
53
- end
54
- end
55
-
56
- def matches?
57
- @cropped_element = @capture_element.crop
58
- if !@trainer_toggle
59
- if File.exists?(@expected_image)
60
- self.compare
61
- else
62
- candidate = self.save_element_as_candidate(@cropped_element)
63
- raise "The design reference #{@expected} does not exist, #{candidate} is now available to be used as a reference. Copy candidate to root reference_image_path to use as reference"
64
- end
65
- else
66
- self.save_element_as_reference(@cropped_element)
67
- matches = true
35
+ if !File.exists?(expected_reference_file)
36
+ save_image_as_candidate(actual_image)
37
+ return false
38
+ else
39
+ expected_image = Gatling::Image.new(:from_file, expected_reference_filename)
40
+ comparison = Gatling::Comparison.new(expected_image, actual_image)
41
+ unless comparison.match
42
+ actual_image.save(:as => :candidate)
43
+ save_image_as_diff(comparison.diff_image)
68
44
  end
45
+ comparison.match
69
46
  end
47
+ end
70
48
 
71
- def compare
72
- expected_img = Magick::Image.read(@expected_image).first
73
-
74
- @diff_metric = @cropped_element.compare_channel(expected_img, Magick::MeanAbsoluteErrorMetric)
49
+ private
75
50
 
76
- matches = @diff_metric[1] == 0.0
51
+ def save_image_as_diff(image)
52
+ image.save(:as => :diff)
53
+ raise "element did not match #{image.file_name}. A diff image: #{image.file_name} was created in " +
54
+ "#{File.join(Gatling::Configuration.paths[:diff],image.file_name)}. " +
55
+ "A new reference #{File.join(Gatling::Configuration.paths[:candidate],image.file_name)} can be used to fix the test"
56
+ end
77
57
 
78
- create_diff unless matches
58
+ def save_image_as_candidate(image)
59
+ image.save :as => :candidate
60
+ raise "The design reference #{image.file_name} does not exist, #{image.path} " +
61
+ "is now available to be used as a reference. Copy candidate to root reference_image_path to use as reference"
62
+ end
79
63
 
80
- matches
64
+ def save_image_as_reference(image)
65
+ if image.exists?
66
+ puts "#{image.path} already exists. reference image was not overwritten. please delete the old file to update using trainer"
67
+ else
68
+ image.save(:as => :reference)
69
+ puts "Saved #{image.path} as reference"
81
70
  end
82
71
  end
83
72
 
73
+ end
84
74
  end
85
-
86
-
87
-
88
-
@@ -1,52 +1,31 @@
1
+ require_relative 'image_wrangler'
2
+
1
3
  module Gatling
2
4
  class CaptureElement
3
5
 
4
- def initialize element_to_capture
6
+ def initialize element_to_capture, *element_to_exclude
5
7
  @reference_image_path = Gatling::Configuration.reference_image_path
6
- @element = element_to_capture
8
+ @element_to_capture = element_to_capture
9
+ @element_to_exclude = element_to_exclude.first
10
+
7
11
  end
8
12
 
9
13
  def capture
10
- temp_dir = "#{@reference_image_path}/temp"
11
14
 
12
- begin
13
- FileUtils::mkdir_p(temp_dir)
14
- rescue
15
- puts "Could not create directory #{temp_dir}. Please make sure you have permission"
16
- end
15
+ screenshot = self.take_screenshot
16
+ screenshot = exclude(screenshot, @element_to_exclude) if @element_to_exclude
17
+ Gatling::ImageWrangler.crop_element(screenshot, @element_to_capture)
18
+ end
17
19
 
20
+ def take_screenshot
21
+ temp_dir = "#{@reference_image_path}/temp"
18
22
  #captures the uncropped full screen
19
23
  begin
20
-
21
24
  Capybara.page.driver.browser.save_screenshot("#{temp_dir}/temp.png")
22
25
  temp_screenshot = Magick::Image.read("#{temp_dir}/temp.png").first
23
26
  rescue
24
27
  raise "Could not save screenshot to #{temp_dir}. Please make sure you have permission"
25
28
  end
26
29
  end
27
-
28
- def crop
29
- element = @element.native
30
- location = element.location
31
- size = element.size
32
- @cropped_element = self.capture.crop(location.x, location.y, size.width, size.height)
33
- end
34
-
35
- def save_element(element, element_name, path)
36
- begin
37
- FileUtils::mkdir_p(path)
38
- rescue
39
- puts "Could not create directory #{path}. Please make sure you have permission"
40
- end
41
-
42
- begin
43
- element.write("#{path}/#{element_name}.png")
44
- element = "#{path}/#{element_name}.png"
45
- rescue
46
- raise "Could not save #{element_name} to #{path}. Please make sure you have permission"
47
- end
48
- end
49
-
50
-
51
30
  end
52
31
  end
@@ -0,0 +1,25 @@
1
+ module Gatling
2
+ class Comparison
3
+
4
+ attr_accessor :match, :diff_image
5
+
6
+ def initialize(actual_image, expected_image)
7
+ compare(actual_image, expected_image)
8
+ end
9
+
10
+ def compare(actual_image, expected_image)
11
+ diff_metric = actual_image.image.compare_channel(expected_image.image, Magick::MeanAbsoluteErrorMetric)
12
+ @match = diff_metric[1] == 0.0
13
+ unless @match
14
+ diff_image = diff_metric.first
15
+ @diff_image = Gatling::Image.new(:from_diff, actual_image.file_name, diff_image)
16
+ end
17
+ @match
18
+ end
19
+
20
+ def diff_image
21
+ @diff_image
22
+ end
23
+
24
+ end
25
+ end
@@ -1,35 +1,59 @@
1
- module Gatling
1
+ module Gatling
2
2
  module Configuration
3
3
 
4
4
  class << self
5
5
 
6
- attr_accessor 'reference_image_path', 'trainer_toggle'
6
+ attr_accessor :reference_image_path, :trainer_toggle
7
+
8
+ attr_reader :paths
7
9
 
8
10
  def reference_image_path
9
- begin
10
- @reference_image_path ||= File.join(Rails.root, 'spec/reference_images')
11
- rescue
12
- raise "Not using Rails? Please set the reference_image_path"
13
- end
11
+ @reference_image_path ||= set_default_path
12
+ end
13
+
14
+ def paths
15
+ Hash[reference:reference_image_path,
16
+ candidate:File.join(reference_image_path, 'candidate'),
17
+ diff:File.join(reference_image_path, 'diff'),
18
+ temp:File.join(reference_image_path, 'temp')]
14
19
  end
15
20
 
16
21
  def trainer_toggle
17
22
  @trainer_value = ENV['GATLING_TRAINER']
18
-
23
+
19
24
  case @trainer_value
20
25
  when nil
21
26
  @trainer_value = nil
22
27
  when 'true'
23
28
  @trainer_value = true
24
29
  when 'false'
25
- @trainer_value = false
30
+ @trainer_value = false
26
31
  else
27
32
  @trainer_value = false
28
- puts 'Unknown GATLING_TRAINER argument. Please supply true, false or nil. DEFAULTING TO FALSE'
33
+ puts 'Unknown GATLING_TRAINER argument. Please supply true, false or nil. DEFAULTING TO FALSE'
29
34
  end
30
35
  @trainer_toggle ||= @trainer_value ||= false
31
36
  end
32
37
 
38
+ def path_from_type(type)
39
+ if paths.keys.include? type
40
+ return paths[type]
41
+ else
42
+ raise "Unkown image type '#{type}'"
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def set_default_path
49
+ begin
50
+ @reference_image_path ||= File.join(Rails.root, 'spec/reference_images')
51
+ rescue
52
+ @reference_image_path = 'spec/reference_images'
53
+ puts "Currently defaulting to #{@reference_image_path}. Overide this by setting Gatling::Configuration.reference_image_path=[refpath]"
54
+ end
55
+ @reference_image_path
56
+ end
33
57
  end
34
58
 
35
59
  end
@@ -0,0 +1,17 @@
1
+ module Gatling
2
+ class FileHelper
3
+ class << self
4
+
5
+ def make_required_directories
6
+ Gatling::Configuration.paths.each { | key, directory | make_dir directory }
7
+ end
8
+
9
+ private
10
+
11
+ def make_dir(path)
12
+ FileUtils::mkdir_p(File.join(path))
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,50 @@
1
+ module Gatling
2
+ class Image
3
+
4
+ attr_accessor :file_name, :path, :image
5
+
6
+ attr_reader :type
7
+
8
+ def initialize(type, file_name, element_or_image = nil)
9
+
10
+ @file_name = file_name
11
+
12
+ case type
13
+ when :from_file
14
+ @image = image_from_file(file_name)
15
+ when :from_element
16
+ @image = image_from_element(element_or_image)
17
+ when :from_diff
18
+ @image = element_or_image
19
+ else
20
+ raise 'WRONG IMAGE TYPE'
21
+ end
22
+
23
+ end
24
+
25
+ def save type
26
+ @path = File.join(Gatling::Configuration.path_from_type(type[:as]), @file_name)
27
+ @image.write @path
28
+ @path
29
+ end
30
+
31
+ def exists?
32
+ File.exists?(File.join(Gatling::Configuration.path_from_type(:reference), @file_name))
33
+ end
34
+
35
+ private
36
+
37
+ def image_from_element element
38
+ Gatling::CaptureElement.new(element).capture
39
+ end
40
+
41
+ def image_from_file file_name
42
+ Magick::Image.read(File.join(Gatling::Configuration.path_from_type(:reference), file_name)).first
43
+ end
44
+
45
+
46
+ end
47
+
48
+ end
49
+
50
+
@@ -0,0 +1,25 @@
1
+ module Gatling
2
+ class ImageWrangler
3
+
4
+ def self.get_element_position element
5
+
6
+ element = element.native
7
+ position = Hash.new{}
8
+ position[:x] = element.location.x
9
+ position[:y] = element.location.y
10
+ position[:width] = element.size.width
11
+ position[:height] = element.size.height
12
+ position
13
+ end
14
+
15
+ def self.crop_element image, element_to_crop
16
+ position = get_element_position(element_to_crop)
17
+ @cropped_element = image.crop(position[:x], position[:y], position[:width], position[:height])
18
+ end
19
+
20
+ def self.exclude image, element_to_exclude
21
+ end
22
+
23
+
24
+ end
25
+ end
@@ -2,7 +2,6 @@ require 'gatling'
2
2
 
3
3
  RSpec::Matchers.define :look_like do |expected|
4
4
  match do |actual|
5
- compare = Gatling::Comparison.new(expected, actual)
6
- compare.matches?
5
+ compare = Gatling.matches?(expected, actual)
7
6
  end
8
7
  end
@@ -1,3 +1,3 @@
1
1
  module Gatling
2
- VERSION = "1.0.6"
2
+ VERSION = "1.0.7"
3
3
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gatling::CaptureElement do
4
+
5
+ before do
6
+
7
+ capybara_node = mock (Capybara::Node::Element)
8
+ Gatling::Configuration.reference_image_path="./"
9
+ Gatling::CaptureElement.new capybara_node, capybara_node
10
+ end
11
+
12
+
13
+
14
+ # it 'should exclude a specified element from capture' do
15
+ # element_to_capture =
16
+
17
+ # element_to_exclude = 'womething.child'
18
+ # # @cropped_and_censored_element = (element_to_capture, element_to_exclude).exclude
19
+ # @cropped_and_censored_element.should_not equal(@element_to_capture)
20
+ # @cropped_and_censored_element.should_not equal(@element_to_exclude)
21
+ # end
22
+
23
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gatling::Comparison do
4
+
5
+ before do
6
+ apple = Magick::Image.new(100,100) { self.background_color = "green" }
7
+ orange = Magick::Image.new(100,100) { self.background_color = "orange" }
8
+ @apple = Gatling::Image.new(:from_diff, 'apple.png', apple)
9
+ @orange = Gatling::Image.new(:from_diff, 'orange.png', orange)
10
+ end
11
+
12
+ describe 'will compare two images' do
13
+
14
+ it 'will return true if the images are identical' do
15
+ subject = Gatling::Comparison.new(@apple, @apple)
16
+ subject.match.should == true
17
+ end
18
+
19
+ it 'will return false if the images are different' do
20
+ subject = Gatling::Comparison.new(@apple, @orange)
21
+ subject.match.should == false
22
+ end
23
+ end
24
+
25
+ describe 'Diff images' do
26
+ it 'will give us a diff' do
27
+ subject = Gatling::Comparison.new(@apple, @orange)
28
+ subject.diff_image.class.should == Gatling::Image
29
+ end
30
+ end
31
+ end
@@ -1,67 +1,86 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Gatling::Configuration" do
3
+ describe Gatling::Configuration do
4
4
 
5
5
  describe "#reference_image_path" do
6
+ before :each do
7
+ Gatling::Configuration.reference_image_path = nil
8
+ end
6
9
 
7
- before do
8
- begin
9
- # Check that rails exists, otherwise fake it for the test
10
- Module.const_get("Rails")
11
- rescue NameError
12
- module Rails
13
- def self.root
14
- "fake_rails_root"
10
+ describe "Without Rails" do
11
+ it "should default to './spec/reference_images' when not in a rails environment" do
12
+ Gatling::Configuration.reference_image_path.should eql("spec/reference_images")
13
+ end
14
+ end
15
+
16
+ describe "with rails" do
17
+
18
+ before do
19
+ begin
20
+ # Check that rails exists, otherwise fake it for the test
21
+ Module.const_get("Rails")
22
+ rescue NameError
23
+ module Rails
24
+ def self.root
25
+ "fake_rails_root"
26
+ end
15
27
  end
16
28
  end
17
29
  end
18
- end
19
-
20
30
 
31
+ it "should default to <Rails.root>/spec/reference_images in a rails environment" do
32
+ Gatling::Configuration.reference_image_path.should eql("fake_rails_root/spec/reference_images")
33
+ end
21
34
 
22
- it "should default to <Rails.root>/spec/reference_images" do
23
- Gatling::Configuration.reference_image_path.should eql("fake_rails_root/spec/reference_images")
24
- end
35
+ it "should be overrideable in a rails environment" do
36
+ Gatling::Configuration.reference_image_path = "my custom path"
37
+ Gatling::Configuration.reference_image_path.should eql("my custom path")
38
+ end
25
39
 
26
- it "should be overrideable" do
27
- Gatling::Configuration.reference_image_path = "my custom path"
28
- Gatling::Configuration.reference_image_path.should eql("my custom path")
29
40
  end
30
-
31
-
32
- end
41
+ end
33
42
 
34
43
  describe '#trainer_toggle' do
35
44
 
36
45
  it 'should default to false' do
37
46
  Gatling::Configuration.trainer_toggle.should eql(false)
38
47
  end
39
-
48
+
40
49
  it 'can be toggled to true' do
41
50
  Gatling::Configuration.trainer_toggle = true
42
51
  Gatling::Configuration.trainer_toggle.should eql(true)
43
52
  end
44
-
53
+
45
54
  it 'toggeled using GATLING_TRAINER = false' do
46
55
  ENV['GATLING_TRAINER'] = 'false'
47
56
  Gatling::Configuration.trainer_toggle.should eql(false)
48
57
  end
49
-
58
+
50
59
  it 'toggeled using GATLING_TRAINER = true' do
51
60
  ENV['GATLING_TRAINER'] = 'true'
52
61
  Gatling::Configuration.trainer_toggle.should eql(true)
53
62
  end
54
-
63
+
55
64
  it 'toggeled using GATLING_TRAINER = nil' do
56
65
  ENV['GATLING_TRAINER'] = nil
57
66
  Gatling::Configuration.trainer_toggle.should eql(false)
58
67
  end
59
-
68
+
60
69
  after(:each) do
61
70
  Gatling::Configuration.trainer_toggle = false
62
71
  ENV['GATLING_TRAINER'] = nil
63
72
  end
64
-
65
73
  end
66
74
 
75
+ describe 'paths' do
76
+ it 'should return the directory for a type of image' do
77
+ Gatling::Configuration.reference_image_path = "a_path"
78
+ Gatling::Configuration.path_from_type(:temp).should == 'a_path/temp'
79
+ end
80
+
81
+ it 'should thrown an error when you ask for the path of an unknown image type' do
82
+ expect { Gatling::Configuration.path_from_type(:unknown)}.should raise_error "Unkown image type 'unknown'"
83
+ end
84
+ end
85
+
67
86
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gatling::FileHelper do
4
+
5
+ describe ':make_dir' do
6
+ before :all do
7
+ Gatling::Configuration.reference_image_path = './gatling'
8
+ end
9
+
10
+ it 'should make required directories' do
11
+ FileUtils.should_receive(:mkdir_p).with './gatling/candidate'
12
+ FileUtils.should_receive(:mkdir_p).with './gatling/diff'
13
+ FileUtils.should_receive(:mkdir_p).with './gatling'
14
+ FileUtils.should_receive(:mkdir_p).with './gatling/temp'
15
+ Gatling::FileHelper.make_required_directories
16
+ end
17
+ end
18
+ end
data/spec/gatling_spec.rb CHANGED
@@ -1,107 +1,89 @@
1
1
  require 'spec_helper'
2
2
  include Capybara::DSL
3
3
 
4
-
5
4
  describe 'Gatling' do
6
5
 
7
-
8
6
  before(:all) do
9
-
10
- include Rack::Test::Methods
11
-
12
- def app
13
- Sinatra::Application
14
- end
15
-
16
- #expected image to compare with
17
- @example_good_image = 'smiley-faceicon.png'
18
-
19
7
  @spec_support_root = spec_support_root
8
+ @black_box = 'black.png'
9
+ @red_box = 'red.png'
10
+ create_images_for_web_page
20
11
  end
21
12
 
13
+ before(:each) do
14
+ @ref_path = Gatling::Configuration.reference_image_path = File.join(spec_support_root, 'ref_path')
15
+ end
22
16
 
23
17
  after(:each) do
24
18
  remove_refs(@ref_path)
19
+ Gatling::Configuration.trainer_toggle = false
25
20
  end
26
-
27
-
28
-
29
- describe 'creating an initial reference (expected) image' do
30
21
 
31
- before(:each) do
32
- @ref_path = Gatling::Configuration.reference_image_path = File.join(@spec_support_root, 'ref_path')
33
- end
22
+ describe 'Gatling, when no reference image exists' do
34
23
 
35
- it "should notify that no reference exists for image and create a candidate" do
36
- gatling = gatling_for_spec('smiley-faceicon.png')
37
- expect {gatling.matches?}.should raise_error(RuntimeError, "The design reference #{@example_good_image} does not exist, #{@ref_path}/candidate/#{@example_good_image} is now available to be used as a reference. Copy candidate to root reference_image_path to use as reference")
38
- File.exists?(File.join(@ref_path,'candidate','smiley-faceicon.png')).should be_true
39
- end
40
- end
24
+ it "will notify that no reference image exists and create a candidate image" do
25
+ black_element = element_for_spec
26
+ expected_error = "The design reference #{@black_box} does not exist, #{@ref_path}/candidate/#{@black_box} " +
27
+ "is now available to be used as a reference. " +
28
+ "Copy candidate to root reference_image_path to use as reference"
41
29
 
30
+ expect {Gatling.matches?(@black_box, black_element)}.should raise_error(RuntimeError, expected_error)
42
31
 
32
+ File.exists?(File.join(@ref_path, 'candidate', @black_box)).should be_true
33
+ end
34
+ end
43
35
 
44
- describe 'image comparison' do
36
+ describe 'Gatling image comparison' do
45
37
 
46
38
  before(:each) do
47
- # @ready_ref = Gatling::Configuration.reference_image_path = File.join(@spec_support_root, 'ready_candidate_ref')
48
- @ref_path = Gatling::Configuration.reference_image_path = File.join(@spec_support_root, 'ref_path')
49
- save_element_for_test
39
+ create_square_image(@ref_path, 'black')
50
40
  end
51
41
 
52
- it 'images match' do
53
- @gatling = gatling_for_spec('smiley-faceicon.png')
54
- @gatling.matches?.should be_true
42
+ it 'will return true if the images are identical' do
43
+ black_element = element_for_spec('#black')
44
+
45
+ Gatling.matches?(@black_box, black_element).should be_true
55
46
  end
56
47
 
57
- it 'images do not match and diff created' do
58
- #convert -fill none -stroke black -strokewidth 5 smiley-faceicon.png -draw 'arc 155,25 185,45 180' sad-faceicon.png
59
- convert_element_to_bad_element(File.join(@ref_path,"#{@example_good_image}"))
60
- gatling = gatling_for_spec('smiley-faceicon.png')
61
- expect {gatling.matches?}.should raise_error(RuntimeError, "element did not match #{@example_good_image}. A diff image: smiley-faceicon_diff.png was created in #{@ref_path}/diff. A new reference #{@ref_path}/candidate/#{@example_good_image} can be used to fix the test")
62
- File.exists?(File.join(@ref_path,'diff','smiley-faceicon_diff.png')).should be_true
63
- end
48
+ it 'will return false, creates new diff and candidate images if the images are different' do
49
+ red_element = element_for_spec('#red')
50
+ expected_error = "element did not match #{@black_box}. " +
51
+ "A diff image: #{@black_box} was created in #{@ref_path}/diff/#{@black_box}. " +
52
+ "A new reference #{@ref_path}/candidate/#{@black_box} can be used to fix the test"
53
+
54
+ expect {Gatling.matches?(@black_box, red_element)}.should raise_error(RuntimeError, expected_error)
55
+
56
+ File.exists?(File.join(@ref_path,'diff', @black_box)).should be_true
57
+ File.exists?(File.join(@ref_path,'candidate', @black_box)).should be_true
58
+ end
64
59
  end
65
60
 
61
+ describe 'Gatling trainer toggle' do
66
62
 
63
+ it 'will save a reference file if no reference file already exists' do
64
+ Gatling::Configuration.trainer_toggle = true
65
+ File.exists?(File.join(@ref_path, @black_box)).should be_false
66
+ $stdout.should_receive(:puts).with "Saved #{@ref_path}/#{@black_box} as reference"
67
+ black_element = element_for_spec
67
68
 
68
- describe 'trainer toggle' do
69
+ expect {Gatling.matches?(@black_box, black_element)}.should_not raise_error
69
70
 
70
- before(:each) do
71
- @ref_path = Gatling::Configuration.reference_image_path = File.join(@spec_support_root, 'ref_path')
71
+ File.exists?(File.join(@ref_path, @black_box)).should be_true
72
72
  end
73
73
 
74
- it 'should save a reference file to the nominated folder without raising an exception' do
74
+ it 'will warn if a reference already exists and not overwrite it' do
75
+ create_square_image(@ref_path, 'black')
75
76
  Gatling::Configuration.trainer_toggle = true
76
- gatling = gatling_for_spec('smiley-faceicon.png')
77
+ expected_message = " already exists. reference image was not overwritten. " +
78
+ "please delete the old file to update using trainer"
79
+ black_element = element_for_spec
80
+ reference_file_ctime = File.ctime(File.join(@ref_path,@black_box))
81
+
82
+ $stdout.should_receive(:puts).with expected_message
83
+ expect {Gatling.matches?(@black_box, black_element)}.should_not raise_error
77
84
 
78
- expect {gatling.matches?}.should_not raise_error
79
- File.exists?(File.join(@ref_path,'smiley-faceicon.png')).should be_true
80
- end
81
-
82
- it 'should alert that the file should be deleted if a reference already exists and not overwrite file' do
83
- save_element_for_test
84
- Gatling::Configuration.trainer_toggle = true
85
- gatling = gatling_for_spec('smiley-faceicon.png')
86
-
87
- reference_file_ctime = File.ctime(File.join(@ref_path,'smiley-faceicon.png'))
88
85
  sleep(1)
89
- expect {gatling.matches?}.should_not raise_error
90
-
91
- #checks if file was overwritten by comparing the time stamps
92
- reference_file_ctime.eql?(File.ctime(File.join(@ref_path,'smiley-faceicon.png'))).should be_true
86
+ reference_file_ctime.eql?(File.ctime(File.join(@ref_path, @black_box))).should be_true
93
87
  end
94
-
95
88
  end
96
-
97
-
98
-
99
-
100
- # MOCK SELENIUM ELEMENT
101
- # correct size (340px*42px)
102
- # image magick saves screenshot
103
- #create diff creates the correct candidate
104
-
105
-
106
89
  end
107
-
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gatling::Image do
4
+
5
+ before :all do
6
+ Gatling::Configuration.reference_image_path = './image_tests'
7
+ end
8
+
9
+ describe 'should initialize from' do
10
+
11
+ it 'image file type' do
12
+ File.stub(:exists?).and_return true
13
+ image_mock = mock(Magick::Image)
14
+ Magick::Image.should_receive(:read).with('./image_tests/image.png').and_return([image_mock])
15
+
16
+ subject = Gatling::Image.new(:from_file, 'image.png')
17
+ subject.image.should == image_mock
18
+ subject.file_name.should == 'image.png'
19
+ end
20
+
21
+ it 'web element type' do
22
+ mock_element = mock(Capybara::Node::Element)
23
+ mock_capture_element = mock(Gatling::CaptureElement)
24
+ mock_image = mock(Magick::Image)
25
+
26
+ Gatling::CaptureElement.should_receive(:new).and_return mock_capture_element
27
+ mock_capture_element.should_receive(:capture).and_return mock_image
28
+ subject = Gatling::Image.new(:from_element, 'image.png', mock_element)
29
+ subject.image.should == mock_image
30
+ subject.file_name.should == 'image.png'
31
+ end
32
+
33
+ it 'diff image' do
34
+ mock_image = mock(Magick::Image)
35
+ subject = Gatling::Image.new(:from_diff, 'image.png', mock_image)
36
+ subject.image.should == mock_image
37
+ subject.file_name.should == 'image.png'
38
+ end
39
+ end
40
+
41
+ it 'should be ok with nil' do
42
+ pending
43
+ end
44
+
45
+ it 'should save an image to the path for the type' do
46
+ mock_image = mock(Magick::Image)
47
+ mock_image.should_receive(:write).with('./image_tests/temp/image.png').and_return()
48
+ subject = Gatling::Image.new(:from_diff, 'image.png', mock_image)
49
+ subject.image = mock_image
50
+ subject.file_name = 'image.png'
51
+ subject.save(:as => :temp)
52
+ subject.path.should == './image_tests/temp/image.png'
53
+ end
54
+
55
+ it 'should check if a file exists, with the file name and type' do
56
+ mock_image = mock(Magick::Image)
57
+ File.should_receive(:exists?).with './image_tests/image.png'
58
+ subject = Gatling::Image.new(:from_diff, 'image.png', mock_image)
59
+ subject.file_name = 'image.png'
60
+ subject.exists?
61
+ end
62
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gatling::ImageWrangler do
4
+
5
+ class Point
6
+ attr_accessor :x, :y
7
+ end
8
+
9
+ class Size
10
+ attr_accessor :width, :height
11
+ end
12
+
13
+ it 'should get the position of the css element' do
14
+
15
+ #Overiding the stupid public method :y of YAML module
16
+
17
+ location = Point.new
18
+ location.x = 1
19
+ location.y = 2
20
+
21
+ size = Size.new
22
+ size.width = 100
23
+ size.height = 200
24
+
25
+ mock_element = mock
26
+ mock_element.stub(:native).and_return(mock_element)
27
+ mock_element.stub(:location).and_return(location)
28
+ mock_element.stub(:size).and_return(size)
29
+
30
+ position = Gatling::ImageWrangler.get_element_position(mock_element)
31
+
32
+ position[:x].should eql(1)
33
+ position[:y].should eql(2)
34
+ position[:width].should eql(100)
35
+ position[:height].should eql(200)
36
+ end
37
+
38
+
39
+
40
+
41
+ end
@@ -1,46 +1,39 @@
1
1
  require 'spec_helper'
2
2
  include Capybara::DSL
3
3
 
4
-
5
4
  describe 'rspec matcher' do
6
-
5
+
7
6
  before(:all) do
7
+ @black_box = 'black.png'
8
+ @ref_path = Gatling::Configuration.reference_image_path = File.join(spec_support_root, 'ref_path')
9
+ create_images_for_web_page
10
+ end
11
+
12
+ after(:each) do
13
+ Gatling::Configuration.trainer_toggle = false
14
+ remove_refs(@ref_path)
15
+ end
8
16
 
9
- include Rack::Test::Methods
17
+ describe 'initializing and runnin gatling' do
10
18
 
11
- def app
12
- Sinatra::Application
19
+ it 'will pass if images matches refernce' do
20
+ create_square_image(@ref_path, 'black')
21
+ black_element = element_for_spec("#black")
22
+ black_element.should look_like(@black_box)
13
23
  end
14
-
15
- #expected image to compare with
16
- @example_good_image = 'smiley-faceicon.png'
17
24
 
18
- @spec_support_root = spec_support_root
19
-
20
- @ref_path = Gatling::Configuration.reference_image_path = File.join(@spec_support_root, 'ref_path')
21
- end
25
+ it 'will fail if images dosent matches refernce' do
26
+ create_square_image(@ref_path, 'black')
27
+ red_element = element_for_spec("#red")
28
+ expect{red_element.should look_like(@black_box)}.should raise_error
29
+ end
22
30
 
31
+ it 'will return true if it makes a new reference image in trainer mode' do
32
+ Gatling::Configuration.trainer_toggle = true
33
+ black_element = element_for_spec("#black")
34
+ black_element.should look_like(@black_box)
35
+ File.exists?(File.join(@ref_path, @black_box)).should be_true
36
+ end
23
37
 
24
- after(:each) do
25
- remove_refs(@ref_path)
26
- end
27
-
28
- it 'should initialize and run gatling' do
29
-
30
- save_element_for_test
31
-
32
- visit('/')
33
- @element = page.find(:css, "#smiley")
34
- @element.should look_like('smiley-faceicon.png')
35
- end
36
-
37
- it 'should initialize and run training mode when GATLING_TRAINER is toggled' do
38
- ENV['GATLING_TRAINER'] = 'true'
39
-
40
- visit('/')
41
- @element = page.find(:css, "#smiley")
42
- @element.should look_like('smiley-faceicon.png')
43
- File.exists?(File.join(@ref_path,'smiley-faceicon.png')).should be_true
44
38
  end
45
-
46
- end
39
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,68 +1,54 @@
1
- require File.join(File.dirname(__FILE__), '/support/assets/smiley_app')
2
-
3
1
  require 'rubygems'
4
- require 'sinatra'
5
- Sinatra::Application.environment = :test
6
- require 'rack/test'
7
- # require 'spec'
8
- # require 'spec/autorun'
9
- # require 'spec/interop/test'
10
2
  require 'capybara'
11
3
  require 'capybara/dsl'
12
4
  require 'capybara/rspec'
13
5
  require 'gatling'
14
6
  require 'gatling/matchers/look_like_matcher'
15
7
  require 'fileutils'
8
+ require 'pry'
9
+
10
+ #todo: spec folders clean up method
16
11
 
17
12
  RSpec.configure do |config|
18
13
  config.color_enabled = true
19
14
  config.formatter = 'documentation'
20
15
  end
21
16
 
22
- Capybara.app = Sinatra::Application
17
+ Capybara.app_host = "file://#{File.expand_path(File.dirname(__FILE__))}/support/assets"
23
18
  Capybara.default_driver = :selenium
24
-
25
- def app
26
- @app ||= Sinatra::Application
27
- end
28
-
29
- set :run, false
30
- set :environment, :test
19
+ Capybara.run_server = false
31
20
 
32
21
  def remove_refs(dir)
33
- FileUtils.rm_rf dir.to_s
22
+ Dir.glob("#{dir}/**/*.png").each {|image| FileUtils.rm image}
34
23
  end
35
24
 
36
- def gatling_for_spec(expected)
37
- visit('/')
38
- @element = page.find(:css, "#smiley")
39
-
40
- @gatling = Gatling::Comparison.new(expected, @element)
25
+ def element_for_spec(css = '#black')
26
+ visit('/fruit_app.html')
27
+ @element = page.find(:css, css)
41
28
  end
42
29
 
43
30
  def spec_support_root
44
- File.join(File.dirname(__FILE__), 'support')
31
+ File.join(File.dirname(__FILE__), 'support')
45
32
  end
46
33
 
47
- def save_element_for_test
48
- Gatling::Configuration.trainer_toggle = true
49
- gatling_for_spec('smiley-faceicon.png').matches?
50
- Gatling::Configuration.trainer_toggle = false
34
+ def create_images_for_web_page
35
+ asset_path = File.join(spec_support_root, 'assets')
36
+ create_square_image(asset_path, 'black')
37
+ create_square_image(asset_path, 'red')
51
38
  end
52
39
 
53
- def convert_element_to_bad_element(image_file)
54
- #convert -fill none -stroke black -strokewidth 5 smiley-faceicon.png -draw 'arc 155,25 185,45 180' sad-faceicon.png
55
- image = Magick::Image.read(image_file).first
56
- frown = Magick::Draw.new
57
- frown.stroke('black')
58
- frown.stroke_width(5)
59
- frown.fill_opacity(0)
60
- frown.stroke_opacity(10)
61
- frown.arc(155,25,185,45,180,0)
62
- frown.draw(image)
63
- bad_element = image.write(image_file)
64
- end
65
-
66
- #todo: spec folders clean up method
40
+ def create_square_image(path, color)
41
+ # We make the images, rather then check them in because otherwise the comparison tests
42
+ # become very flakey depending on the graphics set up on the computer running them
43
+ FileUtils::mkdir_p(path)
67
44
 
45
+ reference_file = Magick::Image.new(100,100) { self.background_color = 'white' }
46
+ square = Magick::Draw.new
47
+ square.fill_opacity(100)
48
+ square.fill_color(color)
49
+ square.rectangle(10,10, 90,90)
50
+ square.draw(reference_file)
68
51
 
52
+ reference_file.write(File.join(path, "#{color}.png"))
53
+ reference_file
54
+ end
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <head>
5
+ <title>The Smiley Site</title>
6
+ </head>
7
+ <body>
8
+ <img src='./black.png' id="black"/>
9
+ <img src='./red.png' id="red"/>
10
+ </body>
11
+ </html>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gatling
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-28 00:00:00.000000000Z
12
+ date: 2012-03-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rmagick
16
- requirement: &70095506844640 !ruby/object:Gem::Requirement
16
+ requirement: &70287958354680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70095506844640
24
+ version_requirements: *70287958354680
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-core
27
- requirement: &70095506844220 !ruby/object:Gem::Requirement
27
+ requirement: &70287958354160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70095506844220
35
+ version_requirements: *70287958354160
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70095506843800 !ruby/object:Gem::Requirement
38
+ requirement: &70287958353700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70095506843800
46
+ version_requirements: *70287958353700
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: capybara
49
- requirement: &70095506843380 !ruby/object:Gem::Requirement
49
+ requirement: &70287958353180 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70095506843380
57
+ version_requirements: *70287958353180
58
58
  description: Add visual comparison matchers for rspec
59
59
  email:
60
60
  - grotbart@gmail.com
@@ -64,29 +64,36 @@ extra_rdoc_files: []
64
64
  files:
65
65
  - .DS_Store
66
66
  - .gitignore
67
+ - .rbenv-version
68
+ - .rvmrc
67
69
  - Gemfile
68
70
  - Gemfile.lock
69
71
  - LICENSE.txt
70
72
  - README.rdoc
71
73
  - Rakefile
72
- - foo.rb
73
74
  - gatling.gemspec
74
75
  - lib/gatling.rb
75
76
  - lib/gatling/capture_element.rb
77
+ - lib/gatling/comparison.rb
76
78
  - lib/gatling/config.rb
79
+ - lib/gatling/file_helper.rb
80
+ - lib/gatling/image.rb
81
+ - lib/gatling/image_wrangler.rb
77
82
  - lib/gatling/matchers/look_like_matcher.rb
78
83
  - lib/gatling/version.rb
79
84
  - pkg/gatling-0.0.1.gem
80
85
  - reports/rspec_unit_test_output.html
86
+ - spec/capture_spec.rb
87
+ - spec/comparison_spec.rb
81
88
  - spec/configuration_spec.rb
89
+ - spec/file_helper_spec.rb
82
90
  - spec/gatling_spec.rb
91
+ - spec/image_spec.rb
92
+ - spec/image_wrangler_spec.rb
83
93
  - spec/rspec_matcher_spec.rb
84
94
  - spec/spec.opts
85
95
  - spec/spec_helper.rb
86
- - spec/support/assets/public/smiley-faceicon.jpg
87
- - spec/support/assets/smiley-bad.jpg
88
- - spec/support/assets/smiley_app.rb
89
- - spec/support/assets/views/smiley_site.erb
96
+ - spec/support/assets/fruit_app.html
90
97
  homepage: http://github.com/GabrielRotbart/gatling
91
98
  licenses: []
92
99
  post_install_message:
@@ -107,17 +114,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
114
  version: '0'
108
115
  requirements: []
109
116
  rubyforge_project: gatling
110
- rubygems_version: 1.8.12
117
+ rubygems_version: 1.8.10
111
118
  signing_key:
112
119
  specification_version: 3
113
120
  summary: Automated visual testing
114
121
  test_files:
122
+ - spec/capture_spec.rb
123
+ - spec/comparison_spec.rb
115
124
  - spec/configuration_spec.rb
125
+ - spec/file_helper_spec.rb
116
126
  - spec/gatling_spec.rb
127
+ - spec/image_spec.rb
128
+ - spec/image_wrangler_spec.rb
117
129
  - spec/rspec_matcher_spec.rb
118
130
  - spec/spec.opts
119
131
  - spec/spec_helper.rb
120
- - spec/support/assets/public/smiley-faceicon.jpg
121
- - spec/support/assets/smiley-bad.jpg
122
- - spec/support/assets/smiley_app.rb
123
- - spec/support/assets/views/smiley_site.erb
132
+ - spec/support/assets/fruit_app.html
data/foo.rb DELETED
@@ -1,9 +0,0 @@
1
- puts ENV['GEM_PATH']
2
- def foo
3
- puts ">"
4
- bar = false unless ENV['BARRR']='true'
5
- puts ">>>"
6
- puts bar.inspect
7
- end
8
-
9
- foo
Binary file
@@ -1,18 +0,0 @@
1
- require 'sinatra'
2
-
3
- set :app_file, __FILE__
4
-
5
- set :root, File.expand_path(File.dirname(__FILE__))
6
- set :static, true
7
-
8
- get '/' do
9
- erb :smiley_site
10
- end
11
-
12
- get '/root' do
13
- 'root is ' + settings.root
14
- end
15
-
16
- get '/public' do
17
- 'root is ' + settings.public_directory
18
- end
@@ -1,19 +0,0 @@
1
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
- "http://www.w3.org/TR/html4/loose.dtd">
3
- <html>
4
- <head>
5
- <title>The Smiley Site</title>
6
- <style type="text/css">
7
- div {width:100%;}
8
- img
9
- {
10
- border:1
11
- }
12
- </style>
13
- </head>
14
- <body>
15
- <div style="width:340px;text-align:center;float:left;" id="smiley">
16
- <img src="smiley-faceicon.jpg" alt="Smiley" height="42" width="42" />
17
- </div>
18
- </body>
19
- </html>