lopata 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1da20f2c64537408a58e5880567aed444ec8d316
4
+ data.tar.gz: 2d8f0ccf72c30d3891dd0b0ce8eaba4654cc6635
5
+ SHA512:
6
+ metadata.gz: 37590ac64353a64346303e46ff53af169ac6c7064bc71794de18887d719cbe4a44baa82f8ac5e5d7e491f5e75b024ff3504607ee98787773dd8484d489c408b1
7
+ data.tar.gz: 2c32502a4f077ae9ca29886bd98c476991878d029f48f048309ecb9230b12b702fdc72006d44c93d39e860ad76a1ff0143dda781caf55d7db7eeed24777988c3
@@ -0,0 +1,2 @@
1
+ # Lopata - functional acceptance testing
2
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup' # TODO - remove after debugging
3
+ require_relative '../lib/lopata/runner'
4
+ Lopata::Runner.start ARGV
@@ -0,0 +1,2 @@
1
+ require 'lopata/id'
2
+ require 'lopata/config'
@@ -0,0 +1,43 @@
1
+ module Lopata
2
+ module Config
3
+ extend self
4
+
5
+ attr_accessor :build_number, :lopata_host, :only_roles, :role_descriptions, :after_as, :ops
6
+
7
+ def init(env)
8
+ require 'yaml'
9
+ @config = YAML::load(File.open("./config/environments/#{env}.yml")) || {}
10
+ init_db
11
+ @role_descriptions ||= {}
12
+ # init_includes
13
+ end
14
+
15
+ %w{url name readonly}.each do |opt|
16
+ define_method opt do
17
+ raise "RstConfig unititlalized, use RstConfig#init(env) to set environment" unless @config
18
+ @config[opt]
19
+ end
20
+ end
21
+
22
+ def init_db
23
+ ActiveRecord::Base.establish_connection(@config['db']) if @config['db']
24
+ end
25
+
26
+ def init_rspec
27
+ require 'lopata/rspec/dsl'
28
+ require 'lopata/rspec/role'
29
+ ::RSpec.configure do |c|
30
+ c.include Lopata::RSpec::DSL
31
+ c.include Lopata::RSpec::Role
32
+ end
33
+ end
34
+
35
+ def before_start(&block)
36
+ @before_start = block
37
+ end
38
+
39
+ def initialize_test
40
+ @before_start.call if @before_start
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ module Lopata
2
+ module DownloadDir
3
+ RELATIVE_PATH = './tmp/target'
4
+
5
+ extend self
6
+
7
+ def path
8
+ @path ||= File.absolute_path(RELATIVE_PATH).gsub("/", '\\')
9
+ end
10
+
11
+ def empty!
12
+ FileUtils.rm Dir.glob("#{RELATIVE_PATH}/*")
13
+ end
14
+
15
+ def ensure_exist
16
+ FileUtils::mkdir_p RELATIVE_PATH unless Dir.exist?(RELATIVE_PATH)
17
+ end
18
+
19
+ def has_file?(file_name)
20
+ require 'timeout'
21
+ target_file = File.join(RELATIVE_PATH, file_name)
22
+ Timeout.timeout(10) do
23
+ sleep 0.1 until File.exist?(target_file)
24
+ true
25
+ end
26
+ rescue Timeout::Error
27
+ false
28
+ end
29
+
30
+ def init_capybara
31
+ profile = Selenium::WebDriver::Firefox::Profile.new
32
+ profile['browser.download.folderList'] = 2
33
+ profile['browser.download.manager.showWhenStarting'] = false
34
+ ensure_exist
35
+ profile['browser.download.dir'] = path
36
+ profile['browser.download.downloadDir'] = path
37
+ profile['browser.download.defaultFolder'] = path
38
+ profile['browser.helperApps.alwaysAsk.force'] = false
39
+ profile['browser.download.useDownloadDir'] = true
40
+ profile['browser.helperApps.neverAsk.saveToDisk'] =
41
+ "application/octet-stream, application/msword, application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
42
+
43
+ Capybara.register_driver :selenium_with_download do |app|
44
+ Capybara::Selenium::Driver.new(
45
+ app,
46
+ {:browser => :firefox, :profile => profile}
47
+ )
48
+ end
49
+
50
+ Capybara.default_driver = :selenium_with_download
51
+ # Capybara.default_max_wait_time = 10
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ module Lopata
2
+ module Generators
3
+ class App < Thor::Group
4
+ include Thor::Actions
5
+ argument :name
6
+
7
+ def self.source_root
8
+ File.join(File.dirname(__FILE__), 'templates')
9
+ end
10
+
11
+ def create_root_files
12
+ template 'Lopatafile', "#{name}/Lopatafile"
13
+ template 'Gemfile', "#{name}/Gemfile"
14
+ template '.rspec', "#{name}/.rspec"
15
+ template 'config/environments/qa.yml', "#{name}/config/environments/qa.yml"
16
+ template 'config/initializers/capybara.rb', "#{name}/config/initializers/capybara.rb"
17
+ end
18
+
19
+ def init_dirs
20
+ %w{models services pages}.each do |dir|
21
+ empty_directory "#{name}/app/#{dir}"
22
+ end
23
+
24
+ %w{spec config/initializers}.each do |dir|
25
+ empty_directory "#{name}/#{dir}"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+ gem 'selenium-webdriver'
3
+ gem 'rspec', :require => 'spec'
4
+ gem 'rake'
5
+ gem 'activerecord', '~> 4.2.0'
6
+ gem 'capybara', '~> 2.2.1' # fix capybara version to avoid capybara-angular deprication varnings.
7
+ # gem 'capybara-angular'
8
+ gem 'thor'
9
+ # gem 'pg'
10
+ # gem 'factory_girl'
11
+ # gem 'lopata', path: 'vendor/lopata'
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ Encoding.default_external = Encoding::UTF_8
3
+ Encoding.default_internal = Encoding::UTF_8
4
+
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+ require 'active_support/all'
8
+ require 'capybara'
9
+ require 'capybara/angular'
10
+ require 'selenium/webdriver'
11
+ require 'fileutils'
12
+ require 'active_support'
13
+ require 'active_record'
14
+ require 'factory_girl'
15
+ require 'lopata'
16
+
17
+ relative_load_paths = %w[app/pages app/services app/models]
18
+ ActiveSupport::Dependencies.autoload_paths += relative_load_paths
19
+
20
+ Dir["./config/initializers/*.rb"].each { |f| require f }
21
+
@@ -0,0 +1,8 @@
1
+ url: http://yourapp.com
2
+ name: QA
3
+ # db:
4
+ # adapter: postgresql
5
+ # host: localhost
6
+ # username: username
7
+ # password: password
8
+ # database: database
@@ -0,0 +1 @@
1
+ Capybara.default_driver = :selenium if defined? Capybara
@@ -0,0 +1,21 @@
1
+ module Lopata
2
+ module Id
3
+ extend self
4
+
5
+ def next(prefix = nil)
6
+ id = "%d_%d" % [timestamp, seq_num]
7
+ id = "%s_%s" % [prefix, id] if prefix
8
+ id
9
+ end
10
+
11
+ def timestamp
12
+ @timestamp ||= Time.now.strftime("%Y%m%d%H%M%S")
13
+ end
14
+
15
+ def seq_num
16
+ @seq_num ||= 0
17
+ @seq_num += 1
18
+ @seq_num
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ module Lopata
2
+ module RSpec
3
+ module DSL
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def action *contexts, &block
10
+ contexts.each do |context|
11
+ if context.is_a?(Proc)
12
+ action(&context)
13
+ else
14
+ include_context context
15
+ end
16
+ end
17
+ before(:all, &block) if block_given?
18
+ end
19
+
20
+ def setup *contexts, &block
21
+ root_setup = false
22
+ unless @doing_setup
23
+ root_setup = true
24
+ @doing_setup = true
25
+ end
26
+ action *contexts, &block
27
+ if root_setup
28
+ # action Config.after_setup if Config.after_setup
29
+ @doing_setup = false
30
+ end
31
+ end
32
+
33
+ def teardown &block
34
+ after(:all, &block) if block_given?
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,137 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+ require 'httparty'
3
+ require 'json'
4
+ require 'lopata/config'
5
+
6
+ module Lopata
7
+ module RSpec
8
+ class Formatter < ::RSpec::Core::Formatters::BaseFormatter
9
+ ::RSpec::Core::Formatters.register self, :start, :example_passed, :example_pending, :example_failed
10
+
11
+ def start(notification)
12
+ raise "Build number is not initailzed in Lopata::Config" unless Lopata::Config.build_number
13
+ @client = Lopata::Client.new(Lopata::Config.build_number)
14
+ @client.start(notification.count)
15
+ end
16
+
17
+ def example_passed(notification)
18
+ @client.add_attempt(notification.example, Lopata::PASSED)
19
+ end
20
+
21
+ def example_failed(notification)
22
+ example = notification.example
23
+ @client.add_attempt(example, Lopata::FAILED, error_message_for(example), backtrace_for(notification))
24
+ end
25
+
26
+ def example_pending(notification)
27
+ example = notification.example
28
+ @client.add_attempt(example, Lopata::PENDING, example.execution_result.pending_message)
29
+ end
30
+
31
+ private
32
+
33
+ def error_message_for(example)
34
+ exception = example.execution_result.exception
35
+ msg = ''
36
+ msg << "#{exception.class.name}: " unless exception.class.name =~ /RSpec/
37
+ msg << "#{exception.message.to_s}" if exception.message
38
+ msg.blank? ? 'Empty message' : msg
39
+ end
40
+
41
+ def backtrace_for(notification)
42
+ example = notification.example
43
+ exception = example.execution_result.exception
44
+ msg = notification.message_lines.map(&:strip).join("\n")
45
+ msg << "\n"
46
+ if shared_group = find_shared_group(example)
47
+ msg << "# Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\" called from "
48
+ msg << "#{backtrace_line(shared_group.metadata[:example_group][:location])}\n"
49
+ end
50
+ msg
51
+ end
52
+
53
+ def find_shared_group(example)
54
+ group_and_parent_groups(example).find {|group| group.metadata[:shared_group_name]}
55
+ end
56
+
57
+ def group_and_parent_groups(example)
58
+ example.example_group.parent_groups + [example.example_group]
59
+ end
60
+ end
61
+ end
62
+
63
+ PASSED = 0
64
+ FAILED = 1
65
+ PENDING = 2
66
+
67
+ class Client
68
+ include HTTParty
69
+ base_uri Lopata::Config.lopata_host
70
+
71
+ attr_accessor :build_number
72
+
73
+ def initialize(build_number)
74
+ @build_number = build_number
75
+ end
76
+
77
+ def start(count)
78
+ @launch_id = JSON.parse(post("/builds/#{build_number}/launches.json", body: {total: count}).body)['id']
79
+ end
80
+
81
+ def add_attempt(example, status, msg = nil, backtrace = nil)
82
+ test = test_id(example)
83
+ request = { status: status}
84
+ request[:message] = msg if msg
85
+ request[:backtrace] = backtrace if backtrace
86
+ post("/tests/#{test}/attempts.json", body: request)
87
+ inc_finished
88
+ end
89
+
90
+ def test_id(example)
91
+ request = {
92
+ find_or_create: {
93
+ title: example.full_description,
94
+ scenario: example.metadata[:example_group][:full_description],
95
+ build_number: build_number
96
+ }
97
+ }
98
+ response = post("/tests.json", body: request)
99
+ JSON.parse(response.body)["id"]
100
+ end
101
+
102
+ def to_rerun
103
+ get_json("/builds/#{build_number}/suspects.json")
104
+ end
105
+
106
+ def to_full_rescan
107
+ to_rerun + get_json("/builds/#{build_number}/failures.json")
108
+ end
109
+
110
+ private
111
+
112
+ def get_json(url)
113
+ JSON.parse(self.class.get(url).body)
114
+ end
115
+
116
+ def post(*args)
117
+ self.class.post(*args)
118
+ end
119
+
120
+ def patch(*args)
121
+ self.class.patch(*args)
122
+ end
123
+
124
+ def inc_finished
125
+ @finished ||= 0
126
+ @finished += 1
127
+ response = patch("/builds/#{build_number}/launches/#{@launch_id}",
128
+ body: { finished: @finished }.to_json,
129
+ headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
130
+ if response.code == 404
131
+ puts 'Launch has been cancelled. Exit.'
132
+ exit!
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,75 @@
1
+ module Lopata::RSpec::Role
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
6
+ # Filter names
7
+ def self.filter_roles *names
8
+ allowed = Lopata::Config.only_roles
9
+ selected = names.flatten.select { |n| allowed.blank? || allowed.member?(n) }
10
+ # ENV['quick'] ? [selected.first] : selected
11
+ selected
12
+ end
13
+
14
+ # http://jorgemanrubia.net/2010/01/16/using-macros-to-create-custom-example-groups-in-rspec/
15
+ module ClassMethods
16
+ def as *names, &block
17
+ return if current_role && !Lopata::RSpec::Role.filter_roles(*names).include?(current_role)
18
+ if current_role
19
+ self.class_eval(&block)
20
+ else
21
+ Lopata::RSpec::Role.filter_roles(*names).each do |name|
22
+ example_group_class = describe role_description(name), :current_role => name do
23
+ instance_exec &Lopata::Config.after_as if Lopata::Config.after_as
24
+ define_method :current_role do
25
+ name
26
+ end
27
+ end
28
+ example_group_class.class_eval(&block)
29
+ end
30
+ end
31
+ end
32
+
33
+ def except(*names, &block)
34
+ raise "'expecpt' block must be neseted for 'as' block" unless current_role
35
+ return if names.include? current_role
36
+ self.class_eval(&block)
37
+ end
38
+
39
+ def current_role
40
+ metadata[:current_role]
41
+ end
42
+
43
+ # To be redefined in impelemntations so RSpec descriptions to be more verbal
44
+ def role_description(name)
45
+ Lopata::Config.role_descriptions[name] || name
46
+ end
47
+
48
+ def scenario(*args, &block)
49
+ raise "scenario required a name in first argument" unless args.first.is_a? String
50
+ example_group_class = describe(*args)
51
+ example_group_class.nested_with_as(*args, &block)
52
+ end
53
+
54
+ def nested_with_as(*args, &block)
55
+ if (args.last.is_a?(Hash) && args.last[:as])
56
+ roles = args.last[:as]
57
+ roles = [roles] unless roles.is_a?(Array)
58
+ class_eval { as(*roles, &block) }
59
+ else
60
+ class_eval(&block)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ module Lopata
67
+ # Adds the #scenario method to the top-level namespace.
68
+ def self.scenario(*args, &block)
69
+ raise "scenario required a name in first argument" unless args.first.is_a? String
70
+ example_group_class = RSpec.describe(*args)
71
+ example_group_class.nested_with_as(*args, &block)
72
+ # example_group_class.register
73
+ end
74
+ end
75
+
@@ -0,0 +1,7 @@
1
+ module Lopata
2
+ module RSpec
3
+ module Version
4
+ STRING = '0.0.2'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+ require 'thor'
2
+ require_relative 'generators/app'
3
+ require_relative 'config'
4
+
5
+ module Lopata
6
+ class Runner < Thor
7
+ desc 'test', 'Run tests'
8
+ option :env, default: :qa, aliases: 'e'
9
+ option :"no-log", type: :boolean, aliases: 'n'
10
+ option :focus, type: :boolean, aliases: 'f'
11
+ option :rerun, type: :boolean, aliases: 'r'
12
+ option :users, type: :array, aliases: 'u'
13
+ option :build, aliases: 'b'
14
+ def test
15
+ require 'rspec'
16
+
17
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
18
+ ENV['HOME'] = File.absolute_path('.') # disable warning on rspec loading on windows
19
+ Lopata::Config.ops = {
20
+ focus: options[:focus],
21
+ rerun: options[:rerun],
22
+ users: options[:users],
23
+ build: options[:build],
24
+ env: options[:env],
25
+ }
26
+ Lopata::Config.init(options[:env])
27
+ Lopata::Config.initialize_test
28
+
29
+ ::RSpec::Core::Runner.run ['spec']
30
+ end
31
+
32
+ default_task :test
33
+
34
+ register Generators::App, :new, 'lopata new project-name', 'Init new lopata projects'
35
+ end
36
+ end
37
+
38
+ raise 'No Lopatafile found in running dir' unless File.exists?('./Lopatafile')
39
+ eval File.binread('./Lopatafile')
40
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lopata
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Alexey Volochnev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Functional acceptance tesging with rspec
42
+ email: alexey.volochnev@gmail.com
43
+ executables:
44
+ - lopata
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - README.md
49
+ - exe/lopata
50
+ - lib/lopata.rb
51
+ - lib/lopata/config.rb
52
+ - lib/lopata/download_dir.rb
53
+ - lib/lopata/generators/app.rb
54
+ - lib/lopata/generators/templates/.rspec
55
+ - lib/lopata/generators/templates/Gemfile
56
+ - lib/lopata/generators/templates/Lopatafile
57
+ - lib/lopata/generators/templates/config/environments/qa.yml
58
+ - lib/lopata/generators/templates/config/initializers/capybara.rb
59
+ - lib/lopata/id.rb
60
+ - lib/lopata/rspec/dsl.rb
61
+ - lib/lopata/rspec/formatter.rb
62
+ - lib/lopata/rspec/role.rb
63
+ - lib/lopata/rspec/version.rb
64
+ - lib/lopata/runner.rb
65
+ homepage:
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.2.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: lopata-0.0.2
89
+ test_files: []