howitzer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/Gemfile +4 -0
  2. data/Gemfile.lock +113 -0
  3. data/LICENSE +22 -0
  4. data/README.md +44 -0
  5. data/Rakefile +2 -0
  6. data/bin/howitzer +41 -0
  7. data/generators/config/config_generator.rb +24 -0
  8. data/generators/config/templates/cucumber.yml +11 -0
  9. data/generators/config/templates/custom.yml +4 -0
  10. data/generators/config/templates/default.yml +76 -0
  11. data/generators/cucumber/cucumber_generator.rb +31 -0
  12. data/generators/cucumber/templates/common_steps.rb +23 -0
  13. data/generators/cucumber/templates/env.rb +38 -0
  14. data/generators/cucumber/templates/example.feature +16 -0
  15. data/generators/cucumber/templates/transformers.rb +28 -0
  16. data/generators/emails/emails_generator.rb +23 -0
  17. data/generators/emails/templates/example_email.rb +7 -0
  18. data/generators/pages/pages_generator.rb +23 -0
  19. data/generators/pages/templates/example_menu.rb +14 -0
  20. data/generators/pages/templates/example_page.rb +15 -0
  21. data/generators/root/root_generator.rb +25 -0
  22. data/generators/root/templates/.gitignore +20 -0
  23. data/generators/root/templates/Gemfile +4 -0
  24. data/generators/root/templates/Rakefile +4 -0
  25. data/generators/root/templates/boot.rb +16 -0
  26. data/generators/tasks/tasks_generator.rb +22 -0
  27. data/generators/tasks/templates/cucumber.rake +57 -0
  28. data/howitzer.gemspec +36 -0
  29. data/lib/howitzer.rb +5 -0
  30. data/lib/howitzer/helpers.rb +58 -0
  31. data/lib/howitzer/init.rb +5 -0
  32. data/lib/howitzer/utils.rb +14 -0
  33. data/lib/howitzer/utils/capybara_patched.rb +22 -0
  34. data/lib/howitzer/utils/capybara_settings.rb +110 -0
  35. data/lib/howitzer/utils/data_generator/data_storage.rb +41 -0
  36. data/lib/howitzer/utils/data_generator/gen.rb +89 -0
  37. data/lib/howitzer/utils/email/email.rb +46 -0
  38. data/lib/howitzer/utils/email/mail_client.rb +126 -0
  39. data/lib/howitzer/utils/email/mailgun.rb +175 -0
  40. data/lib/howitzer/utils/email/mailgun_helper.rb +35 -0
  41. data/lib/howitzer/utils/locator_store.rb +118 -0
  42. data/lib/howitzer/utils/logger.rb +108 -0
  43. data/lib/howitzer/version.rb +3 -0
  44. data/lib/howitzer/web_page.rb +62 -0
  45. 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,7 @@
1
+ class TestEmail < Email
2
+ SUBJECT = "Test email"
3
+
4
+ def addressed_to?(new_user)
5
+ /Hi #{new_user}/ === plain_text_body
6
+ end
7
+ 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,20 @@
1
+ .idea/
2
+ custom.yml
3
+ bin/
4
+ log/
5
+ eylogs/
6
+ spec/results/
7
+ spec/sandbox/
8
+ tmp/
9
+ *.swp
10
+ *.orig
11
+ .rakeTasks
12
+ .bundle
13
+ .DS_STORE
14
+ *.xml
15
+ *.log
16
+ *.pem
17
+ build-number.txt
18
+ sauce_connect.log*
19
+ *.*~
20
+ capybara-*.html
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+ source "http://gemcutter.org"
3
+
4
+ gem 'howitzer'
@@ -0,0 +1,4 @@
1
+ require 'rake'
2
+
3
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
4
+ ENV['RAKE_TASK'] = ARGV[0] if /^(?:r?spec|cucumber)/ === ARGV[0]
@@ -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,5 @@
1
+ require "howitzer/version"
2
+ require 'howitzer/utils'
3
+ require 'howitzer/init'
4
+ require 'howitzer/helpers'
5
+ require 'howitzer/web_page'
@@ -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,5 @@
1
+ include DataGenerator
2
+ include Capybara::DSL #TODO should be included to webpage instead of global content
3
+
4
+ # Configure mail client
5
+ Mailgun::init(settings.mailgun_api_key)
@@ -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