gatling 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -10,4 +10,4 @@ test*
10
10
  spec/support/ready_candidate_ref/temp/*
11
11
  reports/*
12
12
  vendor/*
13
-
13
+ /.rbenv*
data/Gemfile CHANGED
@@ -1,10 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in gatling.gemspec
4
3
  gemspec
5
-
6
- group :development, :test, :smoke do
7
- gem 'rake'
8
- gem 'rspec-instafail'
9
- gem 'pry'
10
- end
@@ -1,10 +1,10 @@
1
1
  = Gatling
2
2
 
3
- Gatling Comparison allows one to build an Rspec / Capybara custom matcher comparing a :css or :xpath element to a referenced screenshot.
3
+ An integrated visual RSpec matcher which makes real visual testing easy.
4
4
 
5
5
  -------------------------------------
6
6
 
7
- === Installation:
7
+ == Installation:
8
8
 
9
9
  gem install gatling
10
10
 
@@ -16,63 +16,71 @@ In spec_helper.rb :
16
16
  #plug and play custom rspec matcher
17
17
  require 'gatling/matchers/look_like_matcher'
18
18
 
19
- === Usage:
19
+ === Configuration settings:
20
20
 
21
- Identify an element to match, for example:
21
+ ==== Reference_image_path - sets where the reference and diff images are saved to.
22
22
 
23
- @element = page.find(:css, #button)
24
-
25
- Use Gatling's custom matcher (conveniently supplied in the gatling gem) and specify the reference image:
23
+ For Rails application, a default reference images folder will be created at spec/reference_images. This folder is root to all the reference
24
+ images to be compares.
26
25
 
27
- @element.should look_like('button_ref.png')
28
-
29
- Gatling will take care of cropping the element and try and make a targeted match without the noise of the whole page.
26
+ Also created are subfolders:
27
+ - /candidate - will hold candidate images which can be used as reference images
28
+ - /diff - will hold the diff images generated by failed comparison tests
29
+ - /temp - will only ever hold one screenshot at a time, used to create the cropped element
30
30
 
31
+ === max_no_tries - sets how many times Gatling will try and match the element against the reference image. Handy to reduce fragility of tests due to animations and load times. Defaults to 5.
31
32
 
32
- If the matcher fails, the test will fail, an exception will be raised and both a diff image and a new candidate image will be created.
33
+ === Sleep_between_tries - sets the sleep time (in seconds) between match tries (requires max_no_tries > 1). Defaults to 0.5
33
34
 
35
+ === Configuration settings are set with the following:
34
36
 
35
- If no reference image exits, the test will fail, an exception will be raised and a candidate will be created which can be used as a reference.
37
+ Gatling.config do |setting|
38
+ Gatling.reference_image_path = 'my_custom_path'
39
+ Gatling.max_no_tries = 3
40
+ Gatling.sleep_between_tries = 0.7
41
+ end
36
42
 
43
+ GATLING::CONFIGURATION will be depreciated in future versions.
37
44
  -------------------------------------
45
+ === Usage:
38
46
 
39
- === The path config:
47
+ Identify an element to match, for example:
40
48
 
41
- For Rails application, a default reference images folder will be created at spec/reference_images. This folder is root to all the reference
42
- images to be compares.
49
+ @element = page.find(:css, #button)
43
50
 
44
- Also created are subfolders:
45
- - /candidate - will hold candidate images which can be used as reference images
46
- - /diff - will hold the diff images generated by failed comparison tests
47
- - /temp - will only ever hold one screenshot at a time, used to create the cropped element
51
+ Use Gatling's custom matcher (conveniently supplied in the gatling gem) and specify the reference image:
52
+
53
+ @element.should look_like('button_ref.png')
48
54
 
49
- ==== For non-Rails apps or just to change the root reference folder specify in spec_help:
55
+ Gatling will take care of cropping the element and try and make a targeted match without the noise of the whole page.
50
56
 
51
- Gatling::Configuration.reference_image_path = "my custom path"
57
+ If the matcher fails, the test will fail, an exception will be raised and both a diff image and a new candidate image will be created.
52
58
 
59
+ If no reference image exits, the test will fail, an exception will be raised and a candidate will be created which can be used as a reference
60
+ (see Training mode below)
53
61
 
54
62
  -------------------------------------
55
63
 
56
64
  === Training mode:
57
65
 
58
- Gatling can be run in training mode which will create reference images where ones do not exist.
66
+ Gatling can be run in training mode which will create reference images where ones do not exist.
59
67
 
60
- <b>CAUTION: Trainer mode will pass all the test which rely on the Gatling custom matcher, this can mean a false green build.
68
+ <b>CAUTION: Trainer mode will pass all the test which rely on the Gatling custom matcher, this can mean a false green build.
61
69
  Please make sure you are saving 'clean' references</b>
62
70
 
63
71
  Trainer mode will not overwrite existing references. If you are updating, just delete the old reference image.
64
72
 
65
- To set trainer mode, prefix rspec command line with $GATLING_TRAINER = true
73
+ To set trainer mode, prefix rspec command line with $GATLING_TRAINER = true
66
74
 
67
75
 
68
- Example:
76
+ Example:
69
77
  $GATLING_TRAINER = true rspec spec/my_spec.rb
70
78
 
71
79
  -------------------------------------
72
80
 
73
81
  ==== Non-gem dependencies:
74
82
 
75
- Imagemagick must be installed:
83
+ Imagemagick must be installed:
76
84
 
77
85
  $sudo apt-get install imagemagick
78
86
 
@@ -80,7 +88,7 @@ Imagemagick must be installed:
80
88
 
81
89
 
82
90
  == Contributing to gatling
83
-
91
+
84
92
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
85
93
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
86
94
  * Fork the project
data/Rakefile CHANGED
@@ -1,13 +1,23 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core'
3
- require 'rspec/core/rake_task'
3
+ require 'rspec/core/rake_task'
4
4
  require File.expand_path('spec/spec_helper.rb')
5
5
 
6
- task :default => ["run"]
7
6
 
8
- desc "default test run"
9
- RSpec::Core::RakeTask.new(:run) do |t|
7
+ task :default => :full_build
8
+
9
+ desc "full build, run all the tests"
10
+ task :full_build => [:unit, :acceptance]
11
+
12
+ desc "Run unit tests"
13
+ RSpec::Core::RakeTask.new(:unit) do |t|
10
14
  t.pattern = ['spec/*_spec.rb']
11
15
  t.rspec_opts = ['--options', "spec/spec.opts"]
12
16
  end
13
-
17
+
18
+
19
+ desc "Run acceptance tests"
20
+ RSpec::Core::RakeTask.new(:acceptance) do |t|
21
+ t.pattern = ['spec/acceptance/*_spec.rb']
22
+ t.rspec_opts = ['--options', "spec/spec.opts"]
23
+ end
@@ -5,7 +5,7 @@ require "gatling/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "gatling"
7
7
  s.version = Gatling::VERSION
8
- s.authors = ["Gabriel Rotbart, Amanda Koh"]
8
+ s.authors = ["Gabriel Rotbart, Amanda Koh, Mike Bain"]
9
9
  s.email = ["grotbart@gmail.com"]
10
10
  s.homepage = "http://github.com/GabrielRotbart/gatling"
11
11
  s.summary = %q{Automated visual testing}
@@ -18,8 +18,12 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency "rmagick"
22
- s.add_dependency "rspec-core"
23
- s.add_dependency "rspec"
24
- s.add_dependency "capybara"
21
+ s.add_runtime_dependency('rmagick', ['>=2.13.1'])
22
+ s.add_runtime_dependency('rspec-core',['>=2.8.0'])
23
+ s.add_runtime_dependency('rspec',['>=2.8.0'])
24
+ s.add_runtime_dependency('capybara',['>=1.1.2'])
25
+
26
+ s.add_development_dependency('rake',['>=0.9.2'])
27
+ s.add_development_dependency('rspec-instafail',['>=0.1.8'])
28
+ s.add_development_dependency('pry',['>=0.9.8.2'])
25
29
  end
@@ -1,18 +1,12 @@
1
- #Dir["/gatling/*.rb"].each {|file| require file}
2
-
3
1
  require 'RMagick'
4
2
  require 'capybara'
5
3
  require 'capybara/dsl'
6
4
 
7
5
  require 'gatling/config'
8
- require 'gatling/file_helper'
9
6
  require 'gatling/image'
10
7
  require 'gatling/comparison'
11
8
  require 'gatling/capture_element'
12
9
 
13
- # include Gatling::Comparison
14
-
15
- #TODO: Fuzz matches
16
10
  #TODO: Helpers for cucumber
17
11
  #TODO: Make directories as needed
18
12
 
@@ -20,39 +14,58 @@ module Gatling
20
14
 
21
15
  class << self
22
16
 
17
+ attr_accessor :reference_image_path, :max_no_tries, :sleep_between_tries
18
+
23
19
  def matches?(expected_reference_filename, actual_element)
24
20
 
25
- Gatling::FileHelper.make_required_directories
21
+ expected_reference_file = (File.join(Gatling::Configuration.path(:reference), expected_reference_filename))
26
22
 
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)
29
23
 
30
24
  if Gatling::Configuration.trainer_toggle
25
+ actual_image = Gatling::ImageFromElement.new(actual_element, expected_reference_filename)
31
26
  save_image_as_reference(actual_image)
32
27
  return true
33
28
  end
34
29
 
35
30
  if !File.exists?(expected_reference_file)
31
+ actual_image = Gatling::ImageFromElement.new(actual_element, expected_reference_filename)
36
32
  save_image_as_candidate(actual_image)
37
33
  return false
38
34
  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)
35
+ comparison = compare_until_match(actual_element, expected_reference_filename, Gatling::Configuration.max_no_tries)
36
+ matches = comparison.matches?
37
+ if !matches
38
+ comparison.actual_image.save(:as => :candidate)
43
39
  save_image_as_diff(comparison.diff_image)
44
40
  end
45
- comparison.match
41
+ matches
46
42
  end
47
43
  end
48
44
 
49
- private
45
+ def compare_until_match actual_element, expected_reference_filename, max_no_tries
46
+ tries = max_no_tries
47
+ try = 0
48
+ match = false
49
+ expected_image = Gatling::ImageFromFile.new(expected_reference_filename)
50
+ comparison = nil
51
+ while !match && try < tries
52
+ actual_image = Gatling::ImageFromElement.new(actual_element, expected_reference_filename)
53
+ comparison = Gatling::Comparison.new(expected_image, actual_image)
54
+ match = comparison.matches?
55
+ if !match
56
+ sleep 0.5
57
+ try += 1
58
+ puts "Tried to match #{try} times"
59
+ end
60
+ end
61
+ comparison
62
+ end
50
63
 
51
64
  def save_image_as_diff(image)
52
65
  image.save(:as => :diff)
53
66
  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"
67
+ "#{File.join(Gatling::Configuration.path(:diff),image.file_name)}. " +
68
+ "A new reference #{File.join(Gatling::Configuration.path(:candidate),image.file_name)} can be used to fix the test"
56
69
  end
57
70
 
58
71
  def save_image_as_candidate(image)
@@ -70,5 +83,9 @@ module Gatling
70
83
  end
71
84
  end
72
85
 
86
+ def config
87
+ yield
88
+ end
89
+
73
90
  end
74
91
  end
@@ -3,15 +3,16 @@ require_relative 'image_wrangler'
3
3
  module Gatling
4
4
  class CaptureElement
5
5
 
6
+ include ImageWrangler
7
+
6
8
  def initialize element_to_capture, *element_to_exclude
7
9
  @reference_image_path = Gatling::Configuration.reference_image_path
8
10
  @element_to_capture = element_to_capture
9
- @element_to_exclude = element_to_exclude.first
11
+ # @element_to_exclude = element_to_exclude.first
10
12
 
11
13
  end
12
14
 
13
15
  def capture
14
-
15
16
  screenshot = self.take_screenshot
16
17
  screenshot = exclude(screenshot, @element_to_exclude) if @element_to_exclude
17
18
  Gatling::ImageWrangler.crop_element(screenshot, @element_to_capture)
@@ -1,24 +1,20 @@
1
1
  module Gatling
2
2
  class Comparison
3
3
 
4
- attr_accessor :match, :diff_image
4
+ attr_accessor :diff_image, :actual_image, :expected_image
5
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)
6
+ def initialize actual_image, expected_image
7
+ @actual_image = actual_image
8
+ @expected_image = expected_image
9
+ @comparison = @actual_image.image.compare_channel(@expected_image.image, Magick::MeanAbsoluteErrorMetric)
10
+ @match = @comparison[1] == 0.0
11
+ if !@matches
12
+ @diff_image =Gatling::Image.new(@comparison.first, @expected_image.file_name)
16
13
  end
17
- @match
18
14
  end
19
15
 
20
- def diff_image
21
- @diff_image
16
+ def matches?
17
+ @match
22
18
  end
23
19
 
24
20
  end
@@ -1,41 +1,29 @@
1
1
  module Gatling
2
- module Configuration
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, :max_no_tries, :sleep_between_tries
7
7
 
8
8
  attr_reader :paths
9
9
 
10
10
  def reference_image_path
11
- @reference_image_path ||= set_default_path
11
+ Gatling.reference_image_path || @reference_image_path ||= set_default_path
12
12
  end
13
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
+ def max_no_tries
15
+ Gatling.max_no_tries || @max_no_tries ||= 5
19
16
  end
20
17
 
21
- def trainer_toggle
22
- @trainer_value = ENV['GATLING_TRAINER']
23
-
24
- case @trainer_value
25
- when nil
26
- @trainer_value = nil
27
- when 'true'
28
- @trainer_value = true
29
- when 'false'
30
- @trainer_value = false
31
- else
32
- @trainer_value = false
33
- puts 'Unknown GATLING_TRAINER argument. Please supply true, false or nil. DEFAULTING TO FALSE'
34
- end
35
- @trainer_toggle ||= @trainer_value ||= false
18
+ def sleep_between_tries
19
+ Gatling.sleep_between_tries || @sleep_between_tries ||= 0.5
36
20
  end
37
21
 
38
- def path_from_type(type)
22
+ def path(type)
23
+ paths = Hash[:reference => reference_image_path,
24
+ :candidate => File.join(reference_image_path, 'candidate'),
25
+ :diff => File.join(reference_image_path, 'diff'),
26
+ :temp => File.join(reference_image_path, 'temp')]
39
27
  if paths.keys.include? type
40
28
  return paths[type]
41
29
  else
@@ -43,11 +31,28 @@ module Gatling
43
31
  end
44
32
  end
45
33
 
46
- private
34
+ def trainer_toggle
35
+ @trainer_value = ENV['GATLING_TRAINER']
36
+
37
+ case @trainer_value
38
+ when nil
39
+ @trainer_value = nil
40
+ when 'true'
41
+ @trainer_value = true
42
+ when 'false'
43
+ @trainer_value = false
44
+ else
45
+ @trainer_value = false
46
+ puts 'Unknown GATLING_TRAINER argument. Please supply true, false or nil. DEFAULTING TO FALSE'
47
+ end
48
+ @trainer_toggle ||= @trainer_value ||= false
49
+ end
50
+
47
51
 
48
52
  def set_default_path
53
+ private
49
54
  begin
50
- @reference_image_path ||= File.join(Rails.root, 'spec/reference_images')
55
+ @reference_image_path ||= File.join(Rails.root, 'spec/reference_images')
51
56
  rescue
52
57
  @reference_image_path = 'spec/reference_images'
53
58
  puts "Currently defaulting to #{@reference_image_path}. Overide this by setting Gatling::Configuration.reference_image_path=[refpath]"
@@ -57,4 +62,4 @@ module Gatling
57
62
  end
58
63
 
59
64
  end
60
- end
65
+ end
@@ -5,46 +5,50 @@ module Gatling
5
5
 
6
6
  attr_reader :type
7
7
 
8
- def initialize(type, file_name, element_or_image = nil)
8
+ def initialize image, file_name
9
9
 
10
10
  @file_name = file_name
11
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
12
+ @image = image
22
13
 
23
14
  end
24
15
 
25
16
  def save type
26
- @path = File.join(Gatling::Configuration.path_from_type(type[:as]), @file_name)
17
+ path = Gatling::Configuration.path(type[:as])
18
+ FileUtils::mkdir_p(path) unless File.exists?(path)
19
+ @path = File.join(path, @file_name)
27
20
  @image.write @path
28
21
  @path
29
22
  end
30
23
 
31
24
  def exists?
32
- File.exists?(File.join(Gatling::Configuration.path_from_type(:reference), @file_name))
25
+ File.exists?(File.join(Gatling::Configuration.path(:reference), @file_name))
33
26
  end
34
27
 
35
- private
28
+ end
36
29
 
37
- def image_from_element element
38
- Gatling::CaptureElement.new(element).capture
39
- end
30
+ class ImageFromElement < Image
40
31
 
41
- def image_from_file file_name
42
- Magick::Image.read(File.join(Gatling::Configuration.path_from_type(:reference), file_name)).first
32
+ def initialize element, file_name
33
+ super(image, file_name)
34
+
35
+ @image = Gatling::CaptureElement.new(element).capture
43
36
  end
37
+
38
+ #TODO: make save a relevant subclass method
39
+ end
44
40
 
41
+ class ImageFromFile < Image
45
42
 
46
- end
43
+ def initialize file_name
44
+ super(image, file_name)
45
+
46
+ @image = Magick::Image.read(File.join(Gatling::Configuration.path(:reference), @file_name)).first
47
+ end
47
48
 
49
+ #TODO: make save a relevant subclass method
50
+
51
+ end
48
52
  end
49
53
 
50
54