sinatra-unit 0.1.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/.gemtest +0 -0
- data/History.txt +6 -0
- data/Manifest.txt +5 -0
- data/README.txt +84 -0
- data/Rakefile +17 -0
- data/lib/sinatra/unit.rb +104 -0
- data/test/unit/test_no_sessions_app.rb +26 -0
- data/test/unit/test_rack_session_app.rb +22 -0
- data/test/unit/test_unknown_route_error.rb +21 -0
- data/test/unit/test_web_app.rb +105 -0
- metadata +126 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# sinatra-unit
|
2
|
+
|
3
|
+
* http://github.com/snarfmason/sinatra-unit
|
4
|
+
|
5
|
+
Testing harness for Sinatra to make proper unit tests/specs for actions.
|
6
|
+
|
7
|
+
Description
|
8
|
+
-----------
|
9
|
+
|
10
|
+
The idea is to instantiate your Sintra class and then execute the web request blocks on the instance
|
11
|
+
that you have created. It uses the `test_request` method (and shortcuts like `test_get`, `test_put`, etc)
|
12
|
+
to look up the block using the same route matching logic that Sinatra would use when receiving a request
|
13
|
+
from Rack.
|
14
|
+
|
15
|
+
Usage
|
16
|
+
-----
|
17
|
+
|
18
|
+
Basic usage:
|
19
|
+
|
20
|
+
@app = WebApp.new
|
21
|
+
response_body = @app.test_request(:get, '/')
|
22
|
+
|
23
|
+
of course you can do, params:
|
24
|
+
|
25
|
+
response_body = @app.test_request(:get, '/hi', :qsname => 'jon')
|
26
|
+
|
27
|
+
you can set the environment or session (if enabled) with a hash, before a request
|
28
|
+
|
29
|
+
@app.env = { :test => 'hello' }
|
30
|
+
@app.session = { :test => 'hello' }
|
31
|
+
response_body = @app.test_get '/showsession'
|
32
|
+
|
33
|
+
Currently the text of the response is returned from the `test_request` method. If you need access to headers or HTTP status you use the `response` object.
|
34
|
+
|
35
|
+
@app.response.status
|
36
|
+
@app.response.header['Content-Type']
|
37
|
+
|
38
|
+
|
39
|
+
Writing Tests
|
40
|
+
-------------
|
41
|
+
|
42
|
+
basic good route:
|
43
|
+
|
44
|
+
response_body = @app.test_request(:get, '/')
|
45
|
+
assert_equal "hello world", response_body
|
46
|
+
assert_equal 200, @app.response.status
|
47
|
+
assert_equal 'text/html', @app.response.header['Content-Type']
|
48
|
+
|
49
|
+
basic bad route:
|
50
|
+
|
51
|
+
assert_raise Sinatra::Unit::UnknownRouteError do
|
52
|
+
@app.test_get '/wrongroute'
|
53
|
+
end
|
54
|
+
|
55
|
+
basic redirect:
|
56
|
+
|
57
|
+
@app.test_get '/redirect'
|
58
|
+
assert @app.redirect?
|
59
|
+
assert_equal 302, @app.response.status
|
60
|
+
|
61
|
+
you can retrieve instance variables set in request blocks
|
62
|
+
|
63
|
+
# app
|
64
|
+
get '/showobject' do
|
65
|
+
@object = OpenStruct.new :foo => 1, :bar => 2, :baz => 3
|
66
|
+
"foo=#{@object.foo}&bar=#{@object.bar}&baz=#{@object.baz}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# test
|
70
|
+
response_body = @app.test_get '/showobject'
|
71
|
+
assert_equal 'foo=1&bar=2&baz=3', response_body
|
72
|
+
assert_equal 1, @app.variables("object").foo
|
73
|
+
|
74
|
+
you can assert against session values
|
75
|
+
|
76
|
+
# app
|
77
|
+
post '/setsession' do
|
78
|
+
session[:test] = params[:test]
|
79
|
+
end
|
80
|
+
|
81
|
+
# test
|
82
|
+
assert_nil @app.session[:test]
|
83
|
+
@app.test_post '/setsession', :test => 'goodbye'
|
84
|
+
assert_equal 'goodbye', @app.session[:test]
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "hoe"
|
5
|
+
|
6
|
+
Hoe.plugin :isolate
|
7
|
+
# Hoe.plugin :rubyforge
|
8
|
+
|
9
|
+
Hoe.spec "sinatra-unit" do
|
10
|
+
dependency 'sinatra', '~> 1.3.3'
|
11
|
+
|
12
|
+
developer "Jonathan Mason", "jonathan.e.mason@gmail.com"
|
13
|
+
|
14
|
+
license "MIT"
|
15
|
+
end
|
16
|
+
|
17
|
+
# vim: syntax=ruby
|
data/lib/sinatra/unit.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
class Unit
|
5
|
+
VERSION = '0.1.0'
|
6
|
+
|
7
|
+
class UnknownRouteError < StandardError
|
8
|
+
attr_accessor :method, :path, :params
|
9
|
+
def initialize(method, path, params)
|
10
|
+
self.method, self.path, self.params = method, path, params
|
11
|
+
message = "Could not resovle route #{method} #{path} with params #{params.inspect}"
|
12
|
+
super message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class SessionsDisabledError < StandardError ; end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Base
|
20
|
+
def test_sessions_enabled?
|
21
|
+
return true if self.class.sessions?
|
22
|
+
|
23
|
+
used_middleware = self.class.instance_variable_get "@middleware"
|
24
|
+
used_middleware.each do |middleware|
|
25
|
+
return true if middleware.first == Rack::Session::Cookie
|
26
|
+
end
|
27
|
+
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
|
31
|
+
# Normal sinatra session method just returns request.session which passes
|
32
|
+
# through to env['rack.session'] but I don't initialize the request object
|
33
|
+
# until just before the route lookkup, so I need to skip directly to env.
|
34
|
+
def session
|
35
|
+
raise Sinatra::Unit::SessionsDisabledError unless test_sessions_enabled?
|
36
|
+
env['rack.session'] ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# This doesn't exist in regular sinatra, but it's convenient for some tests
|
40
|
+
def session=(session)
|
41
|
+
raise Sinatra::Unit::SessionsDisabledError unless test_sessions_enabled?
|
42
|
+
env['rack.session'] = session
|
43
|
+
end
|
44
|
+
|
45
|
+
# test_request comes mostly from the guts of route! in Sinatra::Base
|
46
|
+
def test_request(method, path, params={})
|
47
|
+
@params = indifferent_params(params)
|
48
|
+
|
49
|
+
@request = Sinatra::Request.new(env)
|
50
|
+
@request.path_info = path # sinatra 1.3.3
|
51
|
+
|
52
|
+
@__protected_ivars = instance_variables + ["@__protected_ivars"]
|
53
|
+
|
54
|
+
# routes are stored by uppercase method, but I wanted the test interface
|
55
|
+
# to accept :get or 'get' as well as 'GET'
|
56
|
+
test_request_internal self.class, method.to_s.upcase
|
57
|
+
end
|
58
|
+
|
59
|
+
def variables(name)
|
60
|
+
name = "@#{name.to_s}"
|
61
|
+
instance_variable_get(name) unless @__protected_ivars.include?(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
# expects @request and @params to be set
|
65
|
+
# Don't call this directly, but I don't believe in private methods
|
66
|
+
def test_request_internal(route_holder, method)
|
67
|
+
raise Sinatra::Unit::UnknownRouteError.new(method,@request.path_info,@params) unless route_holder.respond_to?(:routes)
|
68
|
+
|
69
|
+
if route_holder.routes.has_key? method
|
70
|
+
routes = route_holder.routes[method]
|
71
|
+
routes.each do |pattern, keys, conditions, block|
|
72
|
+
process_route(pattern, keys, conditions) do |*args|
|
73
|
+
return catch(:halt) { block[*args] }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
test_request_internal(route_holder.superclass, method)
|
79
|
+
end
|
80
|
+
|
81
|
+
%w(get post put delete head).each do |method|
|
82
|
+
eval <<-CODE
|
83
|
+
def test_#{method}(path, params={})
|
84
|
+
test_request('#{method}', path, params)
|
85
|
+
end
|
86
|
+
CODE
|
87
|
+
end
|
88
|
+
|
89
|
+
# Sinatra makes new do a bunch of stuff with rack middleware wrappers
|
90
|
+
# that are useful if you're actually running the app, but provides
|
91
|
+
# new! for regular instantiation. I'm just re-standardizing names
|
92
|
+
class << self
|
93
|
+
alias new_with_rack_wrappers new
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.new
|
97
|
+
app = new!
|
98
|
+
app.env ||= {}
|
99
|
+
app.response = Sinatra::Response.new
|
100
|
+
app
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'no_sessions_app'
|
2
|
+
require 'sinatra/unit'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class TestNoSessionsApp < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@app = NoSessionsApp.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_session_show
|
12
|
+
assert_raises Sinatra::Unit::SessionsDisabledError do
|
13
|
+
@app.session = { :test => 'hello' }
|
14
|
+
response_body = @app.test_get '/showsession'
|
15
|
+
assert_equal 'session[test] hello', response_body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_session_set
|
20
|
+
assert_raises Sinatra::Unit::SessionsDisabledError do
|
21
|
+
assert_nil @app.session[:test]
|
22
|
+
@app.test_post '/setsession', :test => 'goodbye'
|
23
|
+
assert_equal 'goodbye', @app.session[:test]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rack_sessions_app'
|
2
|
+
require 'sinatra/unit'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class TestRackSessionsApp < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@app = RackSessionsApp.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_session_show
|
12
|
+
@app.session = { :test => 'hello' }
|
13
|
+
response_body = @app.test_get '/showsession'
|
14
|
+
assert_equal 'session[test] hello', response_body
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_session_set
|
18
|
+
assert_nil @app.session[:test]
|
19
|
+
@app.test_post '/setsession', :test => 'goodbye'
|
20
|
+
assert_equal 'goodbye', @app.session[:test]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'web_app'
|
2
|
+
require 'sinatra/unit'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class TestUnknownRouteError < Test::Unit::TestCase
|
6
|
+
def test_unknown_route_exception_details
|
7
|
+
error = nil
|
8
|
+
begin
|
9
|
+
WebApp.new.test_get '/wrongroute', :wrong_param => 'foobar'
|
10
|
+
rescue => e
|
11
|
+
error = e
|
12
|
+
end
|
13
|
+
|
14
|
+
assert_not_nil error
|
15
|
+
assert_equal 'GET', error.method
|
16
|
+
assert_equal '/wrongroute', error.path
|
17
|
+
assert_equal 'foobar', error.params[:wrong_param]
|
18
|
+
assert_match %r{GET.*/wrongroute.*wrong_param.*foobar}, error.message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'web_app'
|
2
|
+
require 'sinatra/unit'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class TestWebApp < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@app = WebApp.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_returns_hello_world_on_index
|
12
|
+
response_body = @app.test_request(:get, '/')
|
13
|
+
assert_equal "hello world", response_body
|
14
|
+
assert_equal 200, @app.response.status
|
15
|
+
assert_equal 'text/html', @app.response.header['Content-Type']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_returns_goodbye_on_bye
|
19
|
+
response_body = @app.test_request(:get, '/bye')
|
20
|
+
assert_equal "goodbye", response_body
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_has_hello_name
|
24
|
+
response_body = @app.test_request(:get, '/hello/jon')
|
25
|
+
assert_equal "hello jon", response_body
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_returns_for_hi_with_param
|
29
|
+
response_body = @app.test_request(:get, '/hi', :qsname => 'jon')
|
30
|
+
assert_equal "hi jon", response_body
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_work_with_get_wrapped_method
|
34
|
+
response_body = @app.test_get '/'
|
35
|
+
assert_equal "hello world", response_body
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_raises_an_exception_for_unknown_route
|
39
|
+
assert_raise Sinatra::Unit::UnknownRouteError do
|
40
|
+
@app.test_get '/wrongroute'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_works_with_post_data
|
45
|
+
response_body = @app.test_post '/goodnight', :name => 'jon'
|
46
|
+
assert_equal 'post goodnight jon', response_body
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_works_with_pu
|
50
|
+
response_body = @app.test_put '/goodnight', :name => 'jon'
|
51
|
+
assert_equal 'put goodnight jon', response_body
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_works_with_env
|
55
|
+
@app.env = { :test => 'hello' }
|
56
|
+
response_body = @app.test_post '/showenv'
|
57
|
+
assert_equal 'env[test] hello', response_body
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_session_show
|
61
|
+
@app.session = { :test => 'hello' }
|
62
|
+
response_body = @app.test_get '/showsession'
|
63
|
+
assert_equal 'session[test] hello', response_body
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_session_set
|
67
|
+
assert_nil @app.session[:test]
|
68
|
+
@app.test_post '/setsession', :test => 'goodbye'
|
69
|
+
assert_equal 'goodbye', @app.session[:test]
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_instance_variable_retrieval
|
73
|
+
response_body = @app.test_get '/showobject'
|
74
|
+
assert_equal 'foo=1&bar=2&baz=3', response_body
|
75
|
+
assert_equal 1, @app.variables("object").foo
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_only_retrieve_instance_variables_set_in_the_block
|
79
|
+
response_body = @app.test_get '/showobject'
|
80
|
+
assert_nil @app.variables("template_cache")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_do_not_retrieve_protected_instance_variables
|
84
|
+
response_body = @app.test_get '/showobject'
|
85
|
+
assert_nil @app.variables("__protected_ivars")
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_redirect_to_index
|
89
|
+
@app.test_get '/redirect'
|
90
|
+
assert @app.redirect?
|
91
|
+
assert_equal 302, @app.response.status
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_two_requests
|
95
|
+
response_body = @app.test_request(:get, '/')
|
96
|
+
assert_equal "hello world", response_body
|
97
|
+
assert_equal 200, @app.response.status
|
98
|
+
assert_equal 'text/html', @app.response.header['Content-Type']
|
99
|
+
|
100
|
+
@app.test_get '/redirect'
|
101
|
+
assert @app.redirect?
|
102
|
+
assert_equal 302, @app.response.status
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-unit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jonathan Mason
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-04-26 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: sinatra
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 29
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 3
|
32
|
+
- 3
|
33
|
+
version: 1.3.3
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdoc
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 19
|
45
|
+
segments:
|
46
|
+
- 3
|
47
|
+
- 10
|
48
|
+
version: "3.10"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: hoe
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 13
|
60
|
+
segments:
|
61
|
+
- 3
|
62
|
+
- 5
|
63
|
+
version: "3.5"
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
description: ""
|
67
|
+
email:
|
68
|
+
- jonathan.e.mason@gmail.com
|
69
|
+
executables: []
|
70
|
+
|
71
|
+
extensions: []
|
72
|
+
|
73
|
+
extra_rdoc_files:
|
74
|
+
- History.txt
|
75
|
+
- Manifest.txt
|
76
|
+
- README.txt
|
77
|
+
files:
|
78
|
+
- History.txt
|
79
|
+
- Manifest.txt
|
80
|
+
- README.txt
|
81
|
+
- Rakefile
|
82
|
+
- lib/sinatra/unit.rb
|
83
|
+
- test/unit/test_no_sessions_app.rb
|
84
|
+
- test/unit/test_rack_session_app.rb
|
85
|
+
- test/unit/test_unknown_route_error.rb
|
86
|
+
- test/unit/test_web_app.rb
|
87
|
+
- .gemtest
|
88
|
+
homepage: http://github.com/snarfmason/sinatra-unit
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options:
|
93
|
+
- --main
|
94
|
+
- README.txt
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: sinatra-unit
|
118
|
+
rubygems_version: 1.8.25
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: ""
|
122
|
+
test_files:
|
123
|
+
- test/unit/test_no_sessions_app.rb
|
124
|
+
- test/unit/test_rack_session_app.rb
|
125
|
+
- test/unit/test_unknown_route_error.rb
|
126
|
+
- test/unit/test_web_app.rb
|