Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

new config mechanism #9

Merged
merged 10 commits into from
Jan 23, 2015
Merged
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ artifacts
*.swp
.DS_Store
.env
.rspec
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/bskyb-commerce/cezanne.svg?branch=master)](https://travis-ci.org/bskyb-commerce/cezanne)
[![Build Status](https://travis-ci.org/BSkyB/cezanne.svg?branch=master)](https://travis-ci.org/BSkyB/cezanne)

# Cezanne

Expand Down Expand Up @@ -26,10 +26,14 @@ In your spec_helper.rb

RSpec.configure do |config|
config.include Cezanne
config.cezanne = { uid: ENV['build_number'], project_name: 'awesome_app' }
end

The uid should be a unique identifier. We use the build number, but it can be a static string if you don't need
Cezanne.configure do |config|
config.uid = ENV['build_number']
config.project_name = 'awesome_app'
end

The should be a unique identifier. We use the build number, but it can be a static string if you don't need
to keep multiple versions of the screenshots.

In your tests
Expand All @@ -48,7 +52,7 @@ and the browser name & version, to make it easy to check visual regressions on m

## Dependencies

Cezanne uses ImageMagick to compare images. Check with your package manager.
Cezanne uses ImageMagick. Check with your package manager.

Screenshots are stored on Dropbox through the Dropscreen gem. Follow the instructions at https://github.com/bskyb-commerce/dropscreen and make sure to export the access_token

Expand Down
1 change: 1 addition & 0 deletions cezanne.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ Gem::Specification.new do |spec|

spec.add_dependency "rmagick"
spec.add_dependency "dropscreen"
spec.add_dependency "phashion"
end
2 changes: 2 additions & 0 deletions lib/cezanne.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
require "cezanne/version"
require "cezanne/config"
require "cezanne/local_files"
require "cezanne/remote_files"
require "cezanne/image"
require "cezanne/comparison"

module Cezanne


def check_visual_regression_for page_name, opts = {}
screenshot = take_screenshot page_name, opts
Expand Down
7 changes: 2 additions & 5 deletions lib/cezanne/comparison.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
require 'RMagick'

module Cezanne

SIMILARITY_THRESHOLD = 42

def spot_differences_between this, that
width = [this.width, that.width].min
height = [this.height, that.height].min
[this, that].each { |img| img.crop!(width, height) }
this.picture.compare_channel(that.picture, Magick::PeakSignalToNoiseRatioMetric)[1] < SIMILARITY_THRESHOLD

not(this.duplicate? that)
end

end
33 changes: 33 additions & 0 deletions lib/cezanne/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Cezanne

Config = Struct.new(:uid, :project_name, :local_root, :remote_root, :local_files, :remote_files, :comparison_method, :similarity_threshold)

def self.config
@config ||= Cezanne::Config.new
end


def self.configure
config = Cezanne.config

yield config if block_given?

config.comparison_method ||= :peak_signal_to_noise_ratio
config.similarity_threshold ||= (config.comparison_method.eql?(:peak_signal_to_noise_ratio) ? 42 : 15)
config.local_root ||= 'artifacts'
config.remote_root ||= config.project_name
config.local_files ||= Cezanne::LocalFiles.new(config.uid, config.local_root)
config.remote_files ||= Cezanne::RemoteFiles.new(config.uid, config.remote_root)
end

private

def local_files
Cezanne.config.local_files
end

def remote_files
Cezanne.config.remote_files
end

end
20 changes: 19 additions & 1 deletion lib/cezanne/image.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'RMagick'
require 'phashion'

module Cezanne

Expand Down Expand Up @@ -27,6 +28,23 @@ def width
def height
@picture.rows
end
end

def duplicate? other
send(Cezanne.config.comparison_method, other)
end

alias_method :==, :duplicate?

private

def peak_signal_to_noise_ratio other
@picture.compare_channel(other.picture, Magick::PeakSignalToNoiseRatioMetric)[1] > Cezanne.config.similarity_threshold
end

def phash_hamming_distance other
Phashion::Image.new(@path).duplicate? Phashion::Image.new(other.path), threshold: Cezanne.config.similarity_threshold
end

end

end
26 changes: 4 additions & 22 deletions lib/cezanne/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,23 @@

RSpec.configure do |config|

config.add_setting :cezanne

config.before(:all, screenshots: true) do
if self.class.include?(Cezanne)
uid = config.cezanne[:uid]
project_name = config.cezanne[:project_name]
config.cezanne[:local_files] = Cezanne::LocalFiles.new(uid, 'artifacts')
config.cezanne[:remote_files] = Cezanne::RemoteFiles.new(uid, project_name)
begin
config.cezanne[:remote_files].pull(:ref, config.cezanne[:local_files].path_for(:ref))
Cezanne.config.remote_files.pull(:ref, Cezanne.config.local_files.path_for(:ref))
rescue
puts "no reference screenshot exist for project #{project_name}"
puts "no reference screenshot exist for project #{Cezanne.config.project_name}"
end
end
end

config.after(:all, screenshots: true) do
if self.class.include?(Cezanne)
[:new, :diff].each do |key|
config.cezanne[:remote_files].push(config.cezanne[:local_files].path_for(key), key)
Cezanne.config.remote_files.push(Cezanne.config.local_files.path_for(key), key)
end
config.cezanne[:local_files].clean
Cezanne.config.local_files.clean
end
end

end

module Cezanne

def local_files
RSpec.configuration.cezanne[:local_files]
end

def remote_files
RSpec.configuration.cezanne[:remote_files]
end

end
2 changes: 1 addition & 1 deletion lib/cezanne/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Cezanne
VERSION = "0.0.3"
VERSION = "0.1.0"
end
31 changes: 30 additions & 1 deletion spec/cezanne_image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
end

it 'return an error if there is no file at path' do
expect { Cezanne::Image.new('unexistent_file_path') }.to raise_error
expect { Cezanne::Image.new('inexistent_file_path') }.to raise_error
end
end

Expand Down Expand Up @@ -67,4 +67,33 @@

end

describe '#duplicate?' do
let(:other_image) { double('Cezanne::Image') }

it 'compare two images' do
Cezanne.config.comparison_method = :comparison_method
allow(image).to receive(:comparison_method)
expect(image).to receive(:comparison_method).with(other_image)
image.duplicate? other_image
end

it 'can use peak signal to noise ratio' do
Cezanne.config.comparison_method = :peak_signal_to_noise_ratio
Cezanne.config.similarity_threshold = 42

allow(other_image).to receive(:picture)
expect(image.picture).to receive(:compare_channel).with(other_image.picture, Magick::PeakSignalToNoiseRatioMetric).and_return([nil, 10])
image.duplicate? other_image
end

it 'can use phash hamming distance' do
Cezanne.config.comparison_method = :phash_hamming_distance
Cezanne.config.similarity_threshold = 15

allow(other_image).to receive(:path)
expect_any_instance_of(Phashion::Image).to receive(:duplicate?)
image.duplicate? other_image
end

end
end
78 changes: 47 additions & 31 deletions spec/cezanne_rspec_spec.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
require 'cezanne/rspec'
require 'capybara/rspec'
require 'selenium-webdriver'
require 'pry'


Capybara.app = Rack::Directory.new('spec/images')
Capybara.default_driver = :selenium

RSpec.configure do |config|
config.include Cezanne
config.cezanne = { uid: 'test', project_name: 'cezanne' }
end

describe 'Cezanne RSpec integration', type: :feature, screenshots: true, integration: true do

# wrap each test with before(:all) and after(:all)

before(:all) do
Cezanne.configure do |config|
config.uid = 'test'
config.project_name = 'cezanne'
end
end

# wrap each test with before(:all) and after(:all); since local folders are creted within the Cezanne.configure and
# cleaned in a after(:all) hook, we need to tweak that in order for the tests to work

after(:all) do |example|
RSpec.configuration.after(:all, screenshots: true).last.instance_variable_set(:@block, Proc.new {}) # disable the after(:all) hook
Cezanne.config.local_files.clean
end

before(:each) do |example|
Expand All @@ -26,13 +32,9 @@

after(:each) do |example|
RSpec.configuration.after(:all, screenshots: true).last.run(example) unless example.metadata[:after_hook_test]
Cezanne.config.local_files = Cezanne::LocalFiles.new(Cezanne.config.uid, Cezanne.config.local_root)
end






describe 'initialization' do

it 'create local folders' do
Expand All @@ -52,41 +54,55 @@

describe 'take screenshots' do

context 'similar' do
{phash_hamming_distance: 'phash hamming distance', peak_signal_to_noise_ratio: 'peak signal to noise ratio'}.each do |key, value|

context value do

before(:all) do
Cezanne.configure do |config|
config.comparison_method = key
end
end

it 'pass the test' do
visit '/similar.html'
expect { check_visual_regression_for 'similar' }.not_to raise_error
end
context 'similar' do

end

context 'different' do
it 'pass the test' do
visit '/similar.html'
expect { check_visual_regression_for 'similar' }.not_to raise_error
end

it 'fail the test' do
visit '/different.html'
expect { check_visual_regression_for 'different' }.to raise_error
end
end

context 'different' do

end
it 'fail the test' do
visit '/different.html'
expect { check_visual_regression_for 'different' }.to raise_error
end


context 'new' do
end


context 'new' do

it 'fail the test' do
visit '/new.html'
expect { check_visual_regression_for 'new' }.to raise_error
end

end

it 'fail the test' do
visit '/new.html'
expect { check_visual_regression_for 'new' }.to raise_error
end

end
end

end

describe 'finalization', after_hook_test: true do

it 'push new, diff screenshots to remote' do |example|
expect(RSpec.configuration.cezanne[:remote_files]).to receive('push').with(kind_of(String), :diff).and_call_original
expect(RSpec.configuration.cezanne[:remote_files]).to receive('push').with(kind_of(String), :new).and_call_original
expect(Cezanne.config.remote_files).to receive('push').with(kind_of(String), :diff).and_call_original
expect(Cezanne.config.remote_files).to receive('push').with(kind_of(String), :new).and_call_original
RSpec.configuration.after(:all, screenshots: true).last.run(example)
end

Expand Down
Loading