futest 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +9 -0
- data/LICENSE +21 -0
- data/README.md +196 -0
- data/config/boot.rb +7 -0
- data/futest.gemspec +19 -0
- data/lib/futest.rb +1 -0
- data/lib/futest/helpers.rb +170 -0
- data/models/model.rb +8 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 224339334e5136b565f5d838828e203f0e74eefb
|
4
|
+
data.tar.gz: 5750d699b9cc98f47250893587ecf2b1f78e5dfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aaf9b7fdbf3ce190129d084bd3340cdb3bc70cd295a2388e453025a76d19c3af5e9bb9ff4643db781b262be852acaa64cad5cc7ea124430ac471257f7d432348
|
7
|
+
data.tar.gz: 255682cbdf14cd3437ff53220ec476a02f2810143f039cee3eabeb80afa0fc0355fa7ec6cf7873b79af48d312a95c364d27b296bd34713dad3748efcd1dffdce
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Fugroup
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
# Futest flexible testing for Ruby
|
2
|
+
|
3
|
+
Test driven development has never been easier. If you like to write scripts instead of tests, and not worry about how your testing framework works, then Futest will give you exactly what you need.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
```
|
7
|
+
gem install futest
|
8
|
+
```
|
9
|
+
or add to Gemfile. In your tests include the line
|
10
|
+
```ruby
|
11
|
+
include Futest::Helpers
|
12
|
+
```
|
13
|
+
and you're good to go.
|
14
|
+
|
15
|
+
### Settings
|
16
|
+
```ruby
|
17
|
+
# The command to run when you use 'show' to show the @body from the last pull.
|
18
|
+
# The default is for MacOs. The -g flag opens the page in the background.
|
19
|
+
Futest.show = 'open -g'
|
20
|
+
|
21
|
+
# Mode, default is development
|
22
|
+
Futest.mode = ENV['RACK_ENV'] || 'development'
|
23
|
+
|
24
|
+
# Debug
|
25
|
+
Futest.debug = false
|
26
|
+
```
|
27
|
+
|
28
|
+
### Commands
|
29
|
+
- **test:** Takes a message and optional setup methods, then prints the message and current line number.
|
30
|
+
- **stop:** Stop test and print message along with line number.
|
31
|
+
- **is:** Checks if something is true and stops if it isn't. See the usage section below.
|
32
|
+
- **pull:** Pulls a URL and expose varibles with info you can use.
|
33
|
+
- **show:** Shows the body from the last pull in your web browser.
|
34
|
+
- **err:** Print formatted exception error message and stops the test.
|
35
|
+
|
36
|
+
### Usage
|
37
|
+
For a real-world example with a test runner ready, have a look at [the tests for Futest.](https://github.com/fugroup/futest/tree/master/test)
|
38
|
+
```ruby
|
39
|
+
# Require futest if not using Bundler
|
40
|
+
require 'futest'
|
41
|
+
|
42
|
+
# Include the Futest helpers in your test runner
|
43
|
+
include Futest::Helpers
|
44
|
+
|
45
|
+
# Run the tests from your app root directory
|
46
|
+
ruby test/run.rb
|
47
|
+
|
48
|
+
# Auto-test with Rerun, Guard or other libraries
|
49
|
+
Rerun: https://github.com/alexch/rerun
|
50
|
+
gem 'rerun'
|
51
|
+
gem 'rb-fsevent'
|
52
|
+
gem 'terminal-notifier'
|
53
|
+
|
54
|
+
# Example command for Rerun, can be added to a shell alias
|
55
|
+
bundle exec rerun --dir .,config --pattern '**/*.{rb,ru,yml}' -- ruby test/run.rb
|
56
|
+
|
57
|
+
# Use begin to have formatted output on error
|
58
|
+
begin
|
59
|
+
|
60
|
+
# Print string in green
|
61
|
+
test 'Testing Heliocentric Model'
|
62
|
+
|
63
|
+
# Optionally pass setup methods to run as symbols
|
64
|
+
# define setup methods
|
65
|
+
def setup; @hello = 'Welcome to the curve.'; end
|
66
|
+
|
67
|
+
def setup_user
|
68
|
+
@user = User.first
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'Reality', :setup, :setup_user
|
72
|
+
is @user, :a? => User
|
73
|
+
is @hello, 'Welcome to the flatness.'
|
74
|
+
|
75
|
+
# :eq is default, can be omitted
|
76
|
+
is 'horizon', 'curved'
|
77
|
+
is 1, 1
|
78
|
+
is 1, :eq => 1
|
79
|
+
is 1, :gt => 0
|
80
|
+
is 1, :lt => 2
|
81
|
+
is 1, :a? => Integer
|
82
|
+
|
83
|
+
# 1 argument is also allowed
|
84
|
+
is 'everything' == 'stories'
|
85
|
+
|
86
|
+
# Use stop to end the test run
|
87
|
+
stop "Can't process" if :earth == 'flat'
|
88
|
+
|
89
|
+
# Pass the validated model object to print the error messages
|
90
|
+
@user = User.first
|
91
|
+
@user.name = "Truth"
|
92
|
+
|
93
|
+
stop "Can't believe user", @user unless @user.save
|
94
|
+
|
95
|
+
# Here are the tests that show how it works
|
96
|
+
# There options are:
|
97
|
+
# :a?, :eq, :lt, :lte, :gt, :gte, :in, :nin, :has
|
98
|
+
s = 'hello'
|
99
|
+
is s, 'hello'
|
100
|
+
is s == 'hello', true
|
101
|
+
is s != 'hello', false
|
102
|
+
is s.start_with?('h'), true
|
103
|
+
is nil, NilClass
|
104
|
+
|
105
|
+
is 1, 1
|
106
|
+
is 1, Integer
|
107
|
+
is 1, :a? => Integer
|
108
|
+
is 1, :eq => 1
|
109
|
+
is 1, :lt => 2
|
110
|
+
is 1, :lte => 2
|
111
|
+
is 2, :lte => 2
|
112
|
+
is 2, :gte => 2
|
113
|
+
is 3, :gte => 2
|
114
|
+
is 6, :gte => 2
|
115
|
+
is 1, :in => [1,2,3]
|
116
|
+
is 5, :nin => [1,2,3]
|
117
|
+
is({:test => 1}, :has => :test)
|
118
|
+
|
119
|
+
# Set up the @host variable to use pull if you want to test requests
|
120
|
+
# The pull format is pull(method = :get, path, params, headers)
|
121
|
+
# Default is :get, but :post, :delete, :update, :patch are supported.
|
122
|
+
|
123
|
+
# You can set the @host globally with $host in stead, or $base for @base
|
124
|
+
# Optionally specify a @base variable to pre-add a path after the @host
|
125
|
+
@base = '/login' # Optional
|
126
|
+
@host = 'http://waveorb.com' # Required
|
127
|
+
|
128
|
+
# URL will be @host + @base, http://waveorb.com/login in this case
|
129
|
+
pull '/login'
|
130
|
+
pull '/login', :duration => 'long'
|
131
|
+
pull '/login', {:duration => 'long'}, :pjax => '1'
|
132
|
+
|
133
|
+
# The pull command exposes these variables for use with tests
|
134
|
+
is @host, 'http://waveorb.com'
|
135
|
+
is @page, :a? => String
|
136
|
+
is @code, 200
|
137
|
+
is @cookies, :a? => Hash
|
138
|
+
is @headers, :a? => Hash
|
139
|
+
is @raw, :a? => Hash
|
140
|
+
is @history, :a? => Array
|
141
|
+
is @body, :a? => String
|
142
|
+
|
143
|
+
|
144
|
+
# # # # # # # # # # # #
|
145
|
+
# Example test with login
|
146
|
+
|
147
|
+
# Post the email and password to the login resource
|
148
|
+
def login
|
149
|
+
pull :post, '/login', :email => 'vidar@fugroup.net', :password => 'test'
|
150
|
+
end
|
151
|
+
|
152
|
+
# Print the name of the test, and run the login
|
153
|
+
# Cookies will be sent back automatically, so your login works for the duration of the test
|
154
|
+
test 'Profile', :login
|
155
|
+
|
156
|
+
# Now that we're logged in, we can view the profile page
|
157
|
+
pull '/profile'
|
158
|
+
|
159
|
+
# The show command displays the last @body from the pull in the browser
|
160
|
+
show
|
161
|
+
|
162
|
+
# Now @page, @code, @cookies, @headers, @raw, @history, @body, @url is available
|
163
|
+
is @page, :a? => String # => Actually a RestClient response object
|
164
|
+
is @code, 200
|
165
|
+
is @cookies, :a? => Hash
|
166
|
+
is @headers, :a? => Hash
|
167
|
+
is @raw, :a? => Hash
|
168
|
+
is @history, :a? => Array
|
169
|
+
is @body, :a? => String
|
170
|
+
is @url, :a? => String
|
171
|
+
|
172
|
+
# Check if the HTML contains a string
|
173
|
+
is @body.include?('string')
|
174
|
+
|
175
|
+
# Flexible, many ways to do it.
|
176
|
+
is @body =~ /string/, Integer
|
177
|
+
is @body !~ /string/, false
|
178
|
+
is @body =~ /string/, :ne => nil
|
179
|
+
|
180
|
+
rescue => x
|
181
|
+
# You can print more information here if you need to debug
|
182
|
+
puts x.message
|
183
|
+
puts x.backtrace
|
184
|
+
|
185
|
+
# Err prints a short backtrace and the line number, then stops the tests.
|
186
|
+
err x
|
187
|
+
|
188
|
+
# Err takes options as symbols
|
189
|
+
err x, :v # Verbose, prints the full message
|
190
|
+
err x, :vv # Very verbose, prints the full backtrace as well
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
Created and maintained by [Fugroup Ltd.](https://www.fugroup.net) We are the creators of [CrowdfundHQ.](https://crowdfundhq.com)
|
195
|
+
|
196
|
+
`@authors: Vidar`
|
data/config/boot.rb
ADDED
data/futest.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'futest'
|
3
|
+
s.version = '0.1.1'
|
4
|
+
s.date = '2017-01-05'
|
5
|
+
s.summary = "Futest flexible testing for Ruby"
|
6
|
+
s.description = "Program your tests as normal scripts without dependencies, mocks, stubs and rules."
|
7
|
+
s.authors = ["Fugroup Limited"]
|
8
|
+
|
9
|
+
s.add_runtime_dependency 'rest-client', '>= 2.0'
|
10
|
+
|
11
|
+
s.email = 'mail@fugroup.net'
|
12
|
+
s.homepage = 'https://github.com/fugroup/futest'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
end
|
data/lib/futest.rb
CHANGED
@@ -0,0 +1,170 @@
|
|
1
|
+
module Futest
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
CMD = {
|
5
|
+
:a? => 'is', :a => 'is',
|
6
|
+
:eq => '==', :ne => '!=',
|
7
|
+
:gt => '>', :gte => '>=',
|
8
|
+
:lt => '<', :lte => '<=',
|
9
|
+
:in => 'in', :nin => 'nin',
|
10
|
+
:has => 'has'
|
11
|
+
}
|
12
|
+
|
13
|
+
##############
|
14
|
+
# TEST METHODS
|
15
|
+
##############
|
16
|
+
|
17
|
+
# Prints error message and stops execution
|
18
|
+
def stop(str, model = nil, n = line(caller))
|
19
|
+
m = "#{n}: #{str}"
|
20
|
+
|
21
|
+
# Support for errors when using Object DB ORM
|
22
|
+
if model and model.errors and model.errors.any?
|
23
|
+
q = model.errors.messages rescue model.errors
|
24
|
+
m += ":\n=> " + q.each{|k, v| q[k] = v.join(', ')}.to_json[1..-2].gsub('","', '", "')
|
25
|
+
end
|
26
|
+
|
27
|
+
puts red(%{#{m}\n}); exit(0)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Prints the test and runs setup methods
|
31
|
+
def test(*args)
|
32
|
+
n = args[-1].is_a?(Integer) ? args[-1] : line(caller)
|
33
|
+
args.select{|r| r.is_a?(Symbol)}.each{|k| send(k)}
|
34
|
+
puts green("#{n}: #{args[0]}")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Equality tester
|
38
|
+
def is(v1, v2 = :udef, n = line(caller))
|
39
|
+
|
40
|
+
# Use :a? if v2 is not a string and looks like a class
|
41
|
+
v2 = {:a? => v2} if !v2.is_a?(String) and v2.to_s[0] =~ /[A-Z]/
|
42
|
+
|
43
|
+
# Use :eq if v2 is defined and it's not a Hash
|
44
|
+
v2 = {:eq => v2} if v2 != :udef and !v2.is_a?(Hash)
|
45
|
+
|
46
|
+
# Symbolize keys
|
47
|
+
k, v = (v2.is_a?(Hash) ? v2 : {}).inject({}){|q,(k,v)|q[k.to_sym] = v; q}.to_a.flatten
|
48
|
+
|
49
|
+
# Extract values
|
50
|
+
s = ["#{v1.class} #{v1} #{CMD[k]} #{v.class} #{v}", nil, n]
|
51
|
+
|
52
|
+
# Set @debug = true to print info
|
53
|
+
puts s.join('-') if @debug
|
54
|
+
|
55
|
+
# Stop unless true
|
56
|
+
stop(*s) unless
|
57
|
+
case k
|
58
|
+
when nil then !!v1
|
59
|
+
when :eq then v1 == v
|
60
|
+
when :ne then v1 != v
|
61
|
+
when :gt then v1 > v
|
62
|
+
when :gte then v1 >= v
|
63
|
+
when :lt then v1 < v
|
64
|
+
when :lte then v1 <= v
|
65
|
+
when :in then v2[:in].include?(v1)
|
66
|
+
when :nin then !v2[:nin].include?(v1)
|
67
|
+
when :has then v1.has_key?(v2[:has])
|
68
|
+
when :a?, :a then v1.is_a?(v)
|
69
|
+
else false end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
##############
|
74
|
+
# REQUEST HELPERS
|
75
|
+
##############
|
76
|
+
|
77
|
+
# Pulls any data source and returns the response
|
78
|
+
def pull(*args)
|
79
|
+
# Define $host in your test helper
|
80
|
+
# or @host before you call pull
|
81
|
+
# set @base to add paths to @host
|
82
|
+
@host ||= $host
|
83
|
+
@base ||= ($base || '')
|
84
|
+
stop('@host not defined') unless @host
|
85
|
+
|
86
|
+
@method = args[0].is_a?(Symbol) ? args.delete_at(0) : :get
|
87
|
+
@path = (args[0] || '/')
|
88
|
+
@params = (args[1] || {})
|
89
|
+
@headers = (args[2] || {})
|
90
|
+
@headers.merge!(:cookies => @cookies) if @cookies
|
91
|
+
|
92
|
+
args.each do |a|
|
93
|
+
@params.merge!(a) if a.is_a?(Hash)
|
94
|
+
@method = a if a.is_a?(Symbol)
|
95
|
+
@path = a if a.is_a?(String)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Add host and base to url
|
99
|
+
@url = @host + (@base || '') + @path
|
100
|
+
|
101
|
+
o = {
|
102
|
+
:method => @method,
|
103
|
+
:url => @url,
|
104
|
+
:timeout => 2,
|
105
|
+
:payload => @params,
|
106
|
+
:headers => @headers
|
107
|
+
}
|
108
|
+
RestClient::Request.execute(o){|z| @page = z}
|
109
|
+
# Make result available in instance variables
|
110
|
+
[:code, :cookies, :headers, :history].each{|i| instance_variable_set("@#{i}", @page.send(i))}
|
111
|
+
@raw = @page.raw_headers
|
112
|
+
@body = @page.body
|
113
|
+
end
|
114
|
+
|
115
|
+
# Show the last @body in the browser
|
116
|
+
def show
|
117
|
+
stop('@body is not defined') unless @body
|
118
|
+
|
119
|
+
# Add @host and @base to all links in HTML to fetch CSS and images
|
120
|
+
@body.scan(/(<.*(src|href)=["'](\/?.+)["'].*>)/).each do |m|
|
121
|
+
@body.gsub!(m[0], m[0].gsub(m[2], "#{@host}#{@base}#{m[2][0] == '/' ? m[2] : "/#{m[2]}"}")) unless %w[ht //].include?(m[2][0..1])
|
122
|
+
end
|
123
|
+
|
124
|
+
# Write body to tmp file
|
125
|
+
name = "/tmp/#{Time.now.to_i}_fushow.html"
|
126
|
+
File.open(name, 'w'){|f| f.write(@body)}
|
127
|
+
|
128
|
+
# Open with default browser, set Futest.show to change this
|
129
|
+
`#{Futest.show} #{name}`
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
##############
|
134
|
+
# HELPER METHODS
|
135
|
+
##############
|
136
|
+
|
137
|
+
# Colorize output, 33 is :green (default), 31 is :red
|
138
|
+
def out(s, c = :green)
|
139
|
+
z = {:green => 33, :red => 31}; %{\e[#{z[c] || c}m#{s}\e[0m}
|
140
|
+
end
|
141
|
+
|
142
|
+
# Colorize input green
|
143
|
+
def green(s); out(s); end
|
144
|
+
|
145
|
+
# Colorize input red
|
146
|
+
def red(s); out(s, :red); end
|
147
|
+
|
148
|
+
# Print error message
|
149
|
+
def err(*args)
|
150
|
+
x = args[0]
|
151
|
+
|
152
|
+
# Pass :v or :vv to print more information about the error
|
153
|
+
puts x.backtrace.join("\n") if args.include?(:vv)
|
154
|
+
puts x.message if args.include?(:v)
|
155
|
+
|
156
|
+
# Normally just print the first line in the message
|
157
|
+
x.backtrace.first.match(/(\/.+\/.*.rb):(\d{1,9}):/)
|
158
|
+
stop(%{#{x.message}\n=> ~/#{$1.split('/')[3..-1].join('/')}}, nil, $2) if $1 and $2
|
159
|
+
|
160
|
+
# Print more if the backtrace doesn't match
|
161
|
+
stop(%{#{x.message}\n=> #{x.backtrace[0..60].join("\n")}})
|
162
|
+
end
|
163
|
+
|
164
|
+
# Get the line number
|
165
|
+
def line(q)
|
166
|
+
q.first.split(':')[1]
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
data/models/model.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: futest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fugroup Limited
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -31,7 +31,16 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- CHANGELOG.md
|
36
|
+
- Gemfile
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- config/boot.rb
|
40
|
+
- futest.gemspec
|
34
41
|
- lib/futest.rb
|
42
|
+
- lib/futest/helpers.rb
|
43
|
+
- models/model.rb
|
35
44
|
homepage: https://github.com/fugroup/futest
|
36
45
|
licenses:
|
37
46
|
- MIT
|