itg_test 0.0.0

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ # Ignore bundler config
2
+ /.bundle
3
+
4
+ # Mac's file index cache
5
+ .DS_Store
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # itg_test - simple integration test framework
2
+ ## Description
3
+ For Rails apps that are too complicated to be tested with the
4
+ builtin integration test, such as apps that spawn threads
5
+ that update the same database table.
6
+ itg_test overcomes this obstacle by simply starting a server
7
+ and a client in separate processes.
8
+
9
+ ## Installation
10
+ `gem install itg_test`
11
+
12
+ ## Usage
13
+ * Create a `itg` folder under Rail's default test folder by running
14
+ `mkdir test/itg`.
15
+ Now your `test` directory structure should look something like
16
+
17
+ `$ls test`
18
+
19
+ `fixtures functional integration itg test_helper.rb unit`
20
+
21
+ * Write integration tests as you would with Rail's default
22
+ integration test framework. Remember to place them under
23
+ the `itg` folder instead of Rail's default `integration` folder.
24
+ For example, create `test/itg/your_app_test.rb` with the following contents
25
+ ```
26
+ require 'itg_test'
27
+
28
+ class YourAppTest < ItgTest::TestCase
29
+ test 'a complete test' do
30
+ get '/peanuts'
31
+ assert_select 'h3 p:nth-child(3)', 'very yummy'
32
+ ...
33
+ end
34
+ end
35
+ ```
36
+ * Run your itg_test tests with `rake test:itg`
37
+ * itg_test supports the common Rails integration test helpers,
38
+ including `assert_equal`, `assert_difference` and `assert_select` etc.
39
+ * You might find the following script that runs all
40
+ Rails and itg_test tests in one shot handy
41
+ ```
42
+ desc "all tests"
43
+ task 'test:all' => :environment do
44
+ Rake::Task['test'].invoke
45
+ Rake::Task['test:itg'].invoke
46
+ end
47
+ ```
48
+
49
+ ## CONTRIBUTORS:
50
+
51
+ * awaw fumin (@awawfumin)
52
+
53
+ ## LICENSE:
54
+
55
+ Apache License 2.0
56
+
57
+ Copyright (c) 2011-2012, Cardinal Blue
58
+
59
+ Licensed under the Apache License, Version 2.0 (the "License");
60
+ you may not use this file except in compliance with the License.
61
+ You may obtain a copy of the License at
62
+
63
+ <http://www.apache.org/licenses/LICENSE-2.0>
64
+
65
+ Unless required by applicable law or agreed to in writing, software
66
+ distributed under the License is distributed on an "AS IS" BASIS,
67
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68
+ See the License for the specific language governing permissions and
69
+ limitations under the License.
data/itg_test.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'itg_test'
3
+ s.version = '0.0.0'
4
+ s.date = '2012-08-29'
5
+ s.summary = "rails integration test"
6
+ s.description = "for rails apps that are too complicated to be tested with builtin integration test"
7
+ s.authors = ["awawfumin"]
8
+ s.email = 'fumin@cardinalblue.com'
9
+ s.files = [
10
+ ".gitignore",
11
+ "lib/itg_test.rb",
12
+ "lib/itg_test/http_client.rb",
13
+ "lib/itg_test/railtie.rb",
14
+ "lib/itg_test/test_case.rb",
15
+ "lib/tasks/test_itg.rake",
16
+ "itg_test.gemspec",
17
+ "README.md"
18
+ ]
19
+ s.homepage = 'http://cardinalblue.com'
20
+ s.add_runtime_dependency "nokogiri", [">= 0"]
21
+ end
@@ -0,0 +1,82 @@
1
+ require 'net/http'
2
+
3
+ # Synopsis
4
+ # c = ItgTest::HTTPClient.new 'http://localhost:3000'
5
+ # c.get '/scheduled_posts/post_due' => <head></head><body>...</body>
6
+
7
+ module ItgTest; end
8
+ class ItgTest::HTTPClient
9
+ attr_accessor :cookie
10
+ def initialize url
11
+ new_url = if %r|^http://.+$| =~ url || %r|^https://.+$| =~ url
12
+ url
13
+ else
14
+ "http://" + url
15
+ end
16
+ @cookie = ""
17
+ @uri = URI(new_url)
18
+ end
19
+
20
+ def session
21
+ Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == 'https')
22
+ rescue Errno::ECONNREFUSED => e
23
+ sleep(1); retry
24
+ end
25
+
26
+ def get path, query=''
27
+ path = path[0...-1] if path[-1] == "/"
28
+ path = "/#{path}" unless path[0] == "/"
29
+ if query == ''
30
+ _get path
31
+ else
32
+ _get "#{path}?#{to_query(query)}"
33
+ end
34
+ end
35
+
36
+ def _get path, limit = 10
37
+ raise ArgumentError, 'too many HTTP redirects' if limit == 0
38
+ res = session.get(path, {'Cookie'=>@cookie})
39
+ cookie_array = res.get_fields('set-cookie')
40
+ @cookie = cookie_array.collect{|ea| ea[/^.*?;/]}.join if cookie_array
41
+ final_res = handle_res res, limit
42
+ JSON.parse final_res
43
+ rescue JSON::ParserError
44
+ final_res
45
+ end
46
+
47
+ def post path, params
48
+ res = session.post path, to_query(params), {'Cookie'=>@cookie}
49
+ handle_res res
50
+ end
51
+
52
+ def to_query params, namespace=nil
53
+ if params.is_a?(Hash)
54
+ params.collect do |key, value|
55
+ to_query(value, namespace ? "#{namespace}[#{key}]" : key)
56
+ end.sort * '&'
57
+ elsif params.is_a?(Array)
58
+ prefix = "#{namespace}[]"
59
+ params.collect { |value| to_query(value, prefix) }.join '&'
60
+ else
61
+ "#{CGI.escape(namespace.to_s)}=#{CGI.escape(params.to_s)}"
62
+ end
63
+ end
64
+
65
+ def handle_res res, limit=10
66
+ case res
67
+ when Net::HTTPRedirection
68
+ location = res['location']
69
+ warn "redirected to #{location}"
70
+ if %r|^http://.+$| =~ location || %r|^https://.+$| =~ location
71
+ @uri = URI(location)
72
+ _get(@uri.path, limit - 1)
73
+ else
74
+ _get(location, limit - 1)
75
+ end
76
+ when Net::HTTPSuccess
77
+ res.body
78
+ else
79
+ res.value
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,11 @@
1
+ require 'itg_test'
2
+ require 'rails'
3
+ module ItgTest
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :itg_test
6
+
7
+ rake_tasks do
8
+ load "tasks/test_itg.rake"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+ require 'itg_test/http_client'
2
+ require 'nokogiri'
3
+
4
+ module Declarative
5
+ def test name, &block
6
+ test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
7
+ define_method test_name, &block
8
+ end
9
+ end
10
+
11
+ module ItgTest; end
12
+ class ItgTest::TestCase
13
+ extend Declarative
14
+ def run_test
15
+ methods.select{|m| /^test_\w+$/ =~ m.to_s}.each{|m| send(m); print "."}
16
+ puts "\nFinished Tests"
17
+ rescue Exception => e
18
+ puts "#{e.class}: #{e}"
19
+ puts e.backtrace
20
+ ensure
21
+ wait_exit
22
+ end
23
+
24
+ def initialize url, pid
25
+ @pid = pid
26
+ @client = ItgTest::HTTPClient.new url
27
+ end
28
+
29
+ def post path, data
30
+ @response = @client.post path, data
31
+ end
32
+
33
+ def get path
34
+ @response = @client.get path
35
+ end
36
+
37
+ def assert_difference expression, difference=1
38
+ exs = [expression].flatten
39
+ before = exs.map{|e| eval e}
40
+ yield
41
+ exs.each_with_index{ |e, i| assert_equal(before[i] + difference, eval(e), e) }
42
+ end
43
+
44
+ def assert_select selector, content
45
+ unless Nokogiri::HTML(@response).at_css(selector).try(:content) == content
46
+ raise "#{content} doesn't match #{selector} of\n#{@response}"
47
+ end
48
+ end
49
+
50
+ def assert_equal a, b, msg=""
51
+ raise "Expected #{a} == #{b} #{msg}" unless a == b
52
+ end
53
+
54
+ def wait_exit
55
+ child_pids(@pid).each{|p| Process.kill "INT", p} # kill grand_children
56
+ Process.kill "INT", @pid # kill child
57
+ Process.wait
58
+ exit
59
+ end
60
+
61
+ def child_pids pid
62
+ pipe = IO.popen("ps -ef | grep #{pid}")
63
+ pipe.readlines.map do |line|
64
+ parts = line.split(/\s+/)
65
+ parts[2] if parts[3] == pid.to_s and parts[2] != pipe.pid.to_s
66
+ end.compact.map(&:to_i)
67
+ end
68
+ end
data/lib/itg_test.rb ADDED
@@ -0,0 +1,11 @@
1
+ module ItgTest
2
+ require 'itg_test/railtie' if defined?(Rails)
3
+ require 'itg_test/test_case'
4
+ require 'itg_test/http_client'
5
+
6
+ module_function
7
+ def absolute_file_name_to_class_name abs_fn
8
+ fn = abs_fn.match(%r|^/.*/([a-zA-Z_]+)\.rb$|)[1]
9
+ fn.split('_').map{|w| w.capitalize}.join
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+
2
+ desc "integration test"
3
+ task 'test:itg' => :environment do
4
+ Rails.env = 'test'
5
+ Rake::Task['db:fixtures:load'].invoke
6
+ pid = Process.fork
7
+ if pid.nil?
8
+ exec('rails s -e test -p 3006')
9
+ exec('rails s -e test -p 3006 > /dev/null 2>&1')
10
+ else
11
+ Dir[Dir.pwd + '/test/itg/*.rb'].each {|file|
12
+ require file
13
+ Object.const_get(ItgTest.absolute_file_name_to_class_name(file)).
14
+ new('http://localhost:3006', pid).run_test
15
+ }
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itg_test
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - awawfumin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: for rails apps that are too complicated to be tested with builtin integration
31
+ test
32
+ email: fumin@cardinalblue.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - lib/itg_test.rb
39
+ - lib/itg_test/http_client.rb
40
+ - lib/itg_test/railtie.rb
41
+ - lib/itg_test/test_case.rb
42
+ - lib/tasks/test_itg.rake
43
+ - itg_test.gemspec
44
+ - README.md
45
+ homepage: http://cardinalblue.com
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: rails integration test
69
+ test_files: []