howitzer 0.0.1
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/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
|