howitzer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +113 -0
- data/LICENSE +22 -0
- data/README.md +44 -0
- data/Rakefile +2 -0
- data/bin/howitzer +41 -0
- data/generators/config/config_generator.rb +24 -0
- data/generators/config/templates/cucumber.yml +11 -0
- data/generators/config/templates/custom.yml +4 -0
- data/generators/config/templates/default.yml +76 -0
- data/generators/cucumber/cucumber_generator.rb +31 -0
- data/generators/cucumber/templates/common_steps.rb +23 -0
- data/generators/cucumber/templates/env.rb +38 -0
- data/generators/cucumber/templates/example.feature +16 -0
- data/generators/cucumber/templates/transformers.rb +28 -0
- data/generators/emails/emails_generator.rb +23 -0
- data/generators/emails/templates/example_email.rb +7 -0
- data/generators/pages/pages_generator.rb +23 -0
- data/generators/pages/templates/example_menu.rb +14 -0
- data/generators/pages/templates/example_page.rb +15 -0
- data/generators/root/root_generator.rb +25 -0
- data/generators/root/templates/.gitignore +20 -0
- data/generators/root/templates/Gemfile +4 -0
- data/generators/root/templates/Rakefile +4 -0
- data/generators/root/templates/boot.rb +16 -0
- data/generators/tasks/tasks_generator.rb +22 -0
- data/generators/tasks/templates/cucumber.rake +57 -0
- data/howitzer.gemspec +36 -0
- data/lib/howitzer.rb +5 -0
- data/lib/howitzer/helpers.rb +58 -0
- data/lib/howitzer/init.rb +5 -0
- data/lib/howitzer/utils.rb +14 -0
- data/lib/howitzer/utils/capybara_patched.rb +22 -0
- data/lib/howitzer/utils/capybara_settings.rb +110 -0
- data/lib/howitzer/utils/data_generator/data_storage.rb +41 -0
- data/lib/howitzer/utils/data_generator/gen.rb +89 -0
- data/lib/howitzer/utils/email/email.rb +46 -0
- data/lib/howitzer/utils/email/mail_client.rb +126 -0
- data/lib/howitzer/utils/email/mailgun.rb +175 -0
- data/lib/howitzer/utils/email/mailgun_helper.rb +35 -0
- data/lib/howitzer/utils/locator_store.rb +118 -0
- data/lib/howitzer/utils/logger.rb +108 -0
- data/lib/howitzer/version.rb +3 -0
- data/lib/howitzer/web_page.rb +62 -0
- metadata +334 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: Addition
|
2
|
+
In order to avoid silly mistakes
|
3
|
+
As a math idiot
|
4
|
+
I want to be told the sum of two numbers
|
5
|
+
|
6
|
+
Scenario Outline: Add two numbers
|
7
|
+
Given I have entered <input_1> into the calculator
|
8
|
+
And I have entered <input_2> into the calculator
|
9
|
+
When I press <button>
|
10
|
+
Then the result should be <output> on the screen
|
11
|
+
|
12
|
+
Examples:
|
13
|
+
| input_1 | input_2 | button | output |
|
14
|
+
| 20 | 30 | add | 50 |
|
15
|
+
| 2 | 5 | add | 7 |
|
16
|
+
| 0 | 40 | add | 40 |
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#############################################################
|
2
|
+
# TRANSFORMERS #
|
3
|
+
#############################################################
|
4
|
+
Transform /UNIQ_USER(\d*)(?:\[\:(.+)\])?/ do |num, property|
|
5
|
+
res = Gen::given_user_by_number(num)
|
6
|
+
res = res.send(property) if property
|
7
|
+
res
|
8
|
+
end
|
9
|
+
|
10
|
+
Transform /^table:.*$/ do |table|
|
11
|
+
raw = table.raw.map do |array|
|
12
|
+
array.map do |el|
|
13
|
+
res = el
|
14
|
+
|
15
|
+
# UNIQ_USER
|
16
|
+
data = /UNIQ_USER(?<num>\d*)(?:\[\:(?<property>.+)\])?/.match(el)
|
17
|
+
if data
|
18
|
+
res = Gen::given_user_by_number(data[:num])
|
19
|
+
if data[:property]
|
20
|
+
res = res.send(data[:property])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
res
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Cucumber::Ast::Table.new(raw)
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class EmailsGenerator < RubiGen::Base
|
4
|
+
|
5
|
+
def initialize(runtime_args, runtime_options = {})
|
6
|
+
super
|
7
|
+
@destination_root = File.expand_path('emails')
|
8
|
+
end
|
9
|
+
|
10
|
+
def manifest
|
11
|
+
record do |m|
|
12
|
+
m.directory ''
|
13
|
+
m.template 'example_email.rb', 'example_email.rb'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
def banner
|
19
|
+
<<-EOS
|
20
|
+
Creates a simple email class."
|
21
|
+
EOS
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class PagesGenerator < RubiGen::Base
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
5
|
+
super
|
6
|
+
@destination_root = File.expand_path('pages')
|
7
|
+
end
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
record do |m|
|
11
|
+
m.directory ''
|
12
|
+
m.template 'example_page.rb', 'example_page.rb'
|
13
|
+
m.template 'example_menu.rb', 'example_menu.rb'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
def banner
|
19
|
+
<<-EOS
|
20
|
+
Creates PageOriented pattern structure
|
21
|
+
EOS
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ExampleMenu
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
add_locator :menu_button, ".menuButton"
|
5
|
+
add_locator :account, xpath: ".//*[@id='metaMenu']//a[contains(., 'Account')]"
|
6
|
+
add_locator :log_out, xpath: ".//*[@id='metaMenu']//a[contains(., 'Log Out')]"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def open_menu
|
11
|
+
log.info "Open menu"
|
12
|
+
click_link locator(:menu_button)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'example_menu'
|
2
|
+
|
3
|
+
class ExamplePage < WebPage
|
4
|
+
URL = '/'
|
5
|
+
URL_PATTERN = /#{Regexp.escape(settings.app_host)}\/?/
|
6
|
+
|
7
|
+
add_field_locator :search_input, 'lst-ib'
|
8
|
+
add_button_locator :search_btn, 'btnK'
|
9
|
+
|
10
|
+
include ExampleMenu
|
11
|
+
|
12
|
+
def fill_keyword(data)
|
13
|
+
fill_in field_locator(:search_input), data
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class RootGenerator < RubiGen::Base
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
5
|
+
super
|
6
|
+
@destination_root = File.expand_path('')
|
7
|
+
end
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
record do |m|
|
11
|
+
m.directory ''
|
12
|
+
m.template '.gitignore', '.gitignore'
|
13
|
+
m.template 'Gemfile', 'Gemfile'
|
14
|
+
m.template 'Rakefile', 'Rakefile'
|
15
|
+
m.template 'boot.rb', 'boot.rb'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def banner
|
21
|
+
<<-EOF
|
22
|
+
Creates root config files.
|
23
|
+
EOF
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'howitzer'
|
2
|
+
|
3
|
+
Dir.chdir(File.join(File.dirname(__FILE__), '.'))
|
4
|
+
|
5
|
+
def settings
|
6
|
+
SexySettings::Base.instance()
|
7
|
+
end
|
8
|
+
|
9
|
+
if settings.required_clean_logs
|
10
|
+
require 'rake/clean'
|
11
|
+
CLEAN.include("#{settings.log_dir}/*")
|
12
|
+
Rake::Task[:clean].invoke
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir[File.join(File.dirname(__FILE__), "./emails/*.rb")].each {|f| require f}
|
16
|
+
Dir[File.join(File.dirname(__FILE__), "./pages/*.rb")].each {|f| require f}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class TasksGenerator < RubiGen::Base
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
5
|
+
super
|
6
|
+
@destination_root = File.expand_path('tasks')
|
7
|
+
end
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
record do |m|
|
11
|
+
m.directory ''
|
12
|
+
m.template 'cucumber.rake', 'cucumber.rake'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def banner
|
18
|
+
<<-EOF
|
19
|
+
Creates RAKE tasks folder and file.
|
20
|
+
EOF
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
|
3
|
+
begin
|
4
|
+
require 'cucumber'
|
5
|
+
require 'cucumber/rake/task'
|
6
|
+
|
7
|
+
namespace :cucumber do
|
8
|
+
Cucumber::Rake::Task.new({ok: 'db:test:prepare'}, 'Run features that should pass') do |t|
|
9
|
+
t.fork = false # You may get faster startup if you set this to false
|
10
|
+
t.profile = 'default'
|
11
|
+
end
|
12
|
+
|
13
|
+
Cucumber::Rake::Task.new({wip: 'db:test:prepare'}, 'Run features that are being worked on') do |t|
|
14
|
+
t.fork = false # You may get faster startup if you set this to false
|
15
|
+
t.profile = 'wip'
|
16
|
+
end
|
17
|
+
|
18
|
+
Cucumber::Rake::Task.new({bug: 'db:test:prepare'}, 'Run features with known bugs') do |t|
|
19
|
+
t.fork = false # You may get faster startup if you set this to false
|
20
|
+
t.profile = 'bug'
|
21
|
+
end
|
22
|
+
|
23
|
+
Cucumber::Rake::Task.new({demo: 'db:test:prepare'}, 'Run demo feature') do |t|
|
24
|
+
t.fork = false # You may get faster startup if you set this to false
|
25
|
+
t.profile = 'demo'
|
26
|
+
end
|
27
|
+
|
28
|
+
Cucumber::Rake::Task.new({rerun: 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
|
29
|
+
t.fork = false # You may get faster startup if you set this to false
|
30
|
+
t.profile = 'rerun'
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Run all features'
|
34
|
+
task all: [:ok, :wip]
|
35
|
+
|
36
|
+
end
|
37
|
+
desc 'Alias for cucumber:ok'
|
38
|
+
task cucumber: 'cucumber:ok'
|
39
|
+
|
40
|
+
task default: :cucumber
|
41
|
+
|
42
|
+
task features: :cucumber do
|
43
|
+
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
44
|
+
end
|
45
|
+
|
46
|
+
# In case we don't have ActiveRecord, append a no-op task that we can depend upon.
|
47
|
+
task 'db:test:prepare' do
|
48
|
+
end
|
49
|
+
|
50
|
+
rescue LoadError
|
51
|
+
desc 'cucumber rake task not available (cucumber not installed)'
|
52
|
+
task :cucumber do
|
53
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/howitzer.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/howitzer/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Roman Parashchenko, Konstantin Lynda, Nikolay Zozulyak"]
|
6
|
+
gem.email = ["strongqa@gmail.com"]
|
7
|
+
gem.description = %q{The framework is based on Page Object pattern, Capybara and Rspec/Cucumber libraries}
|
8
|
+
gem.summary = %q{Universal Ruby Test Framework for black box testing}
|
9
|
+
gem.homepage = "https://github.com/romikoops/howitzer"
|
10
|
+
|
11
|
+
gem.bindir = 'bin'
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "howitzer"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Howitzer::VERSION
|
18
|
+
gem.required_ruby_version = '~> 1.9.2'
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'rake'
|
21
|
+
gem.add_runtime_dependency 'rubigen'
|
22
|
+
gem.add_runtime_dependency 'i18n'
|
23
|
+
gem.add_runtime_dependency 'cucumber'
|
24
|
+
gem.add_runtime_dependency 'rspec', '~> 2.0'
|
25
|
+
gem.add_runtime_dependency 'sexy_settings'
|
26
|
+
gem.add_runtime_dependency 'repeater'
|
27
|
+
gem.add_runtime_dependency 'selenium-webdriver'
|
28
|
+
gem.add_runtime_dependency 'capybara'
|
29
|
+
gem.add_runtime_dependency 'launchy'
|
30
|
+
gem.add_runtime_dependency 'log4r'
|
31
|
+
gem.add_runtime_dependency 'mail'
|
32
|
+
gem.add_runtime_dependency 'rest-client'
|
33
|
+
gem.add_runtime_dependency 'poltergeist'
|
34
|
+
gem.add_runtime_dependency 'activeresource', '3.2.8'
|
35
|
+
|
36
|
+
end
|
data/lib/howitzer.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
def sauce_driver?
|
3
|
+
settings.driver.to_sym == :sauce
|
4
|
+
end
|
5
|
+
|
6
|
+
def selenium_driver?
|
7
|
+
settings.driver.to_sym == :selenium
|
8
|
+
end
|
9
|
+
|
10
|
+
def ie_browser?
|
11
|
+
ie_browsers = [:ie, :iexplore]
|
12
|
+
if sauce_driver?
|
13
|
+
ie_browsers.include?(settings.sl_browser_name.to_sym)
|
14
|
+
elsif selenium_driver?
|
15
|
+
ie_browsers.include?(settings.sel_browser.to_sym)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def ff_browser?
|
20
|
+
ff_browsers = [:ff, :firefox]
|
21
|
+
if sauce_driver?
|
22
|
+
ff_browsers.include?(settings.sl_browser_name.to_sym)
|
23
|
+
elsif selenium_driver?
|
24
|
+
ff_browsers.include?(settings.sel_browser.to_sym)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def duration(time_in_numeric)
|
30
|
+
secs = time_in_numeric.to_i
|
31
|
+
mins = secs / 60
|
32
|
+
hours = mins / 60
|
33
|
+
if hours > 0
|
34
|
+
"[#{hours}h #{mins % 60}m #{secs % 60}s]"
|
35
|
+
elsif mins > 0
|
36
|
+
"[#{mins}m #{secs % 60}s]"
|
37
|
+
elsif secs >= 0
|
38
|
+
"[0m #{secs}s]"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def ri(value)
|
43
|
+
raise value.inspect
|
44
|
+
end
|
45
|
+
|
46
|
+
class String
|
47
|
+
def open(*args)
|
48
|
+
as_page_class.open(*args)
|
49
|
+
end
|
50
|
+
|
51
|
+
def given
|
52
|
+
as_page_class.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def as_page_class
|
56
|
+
Object.const_get("#{self.capitalize}Page")
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'sexy_settings'
|
2
|
+
require 'repeater'
|
3
|
+
|
4
|
+
SexySettings.configure do |config|
|
5
|
+
config.path_to_default_settings = File.expand_path("config/default.yml", Dir.pwd)
|
6
|
+
config.path_to_custom_settings = File.expand_path("config/custom.yml", Dir.pwd)
|
7
|
+
end
|
8
|
+
|
9
|
+
def settings
|
10
|
+
SexySettings::Base.instance()
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
Dir[File.join(File.dirname(__FILE__), "./utils/**/*.rb")].each {|f| require f}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CapybaraPatched
|
2
|
+
class Capybara::Selenium::PatchedDriver < Capybara::Selenium::Driver
|
3
|
+
RETRY_ON = [
|
4
|
+
::Selenium::WebDriver::Error::UnhandledError,
|
5
|
+
::Selenium::WebDriver::Error::UnknownError,
|
6
|
+
::Selenium::WebDriver::Error::InvalidSelectorError
|
7
|
+
]
|
8
|
+
|
9
|
+
# workaround for transferring correct arguments via call stack
|
10
|
+
Capybara::Session.instance_eval do
|
11
|
+
self::NODE_METHODS.each do |method|
|
12
|
+
class_eval <<-RUBY
|
13
|
+
def #{method}(*args, &block)
|
14
|
+
retryable(tries:3, logger: log, trace: true, on: RETRY_ON) do
|
15
|
+
current_node.send(:#{method}, *args.flatten, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
RUBY
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|