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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35a95d6ea6fbf97288d5911168bec2c8c7a4d63b
4
- data.tar.gz: 82d69b0048efe37201021c0f3799defba323045c
3
+ metadata.gz: 224339334e5136b565f5d838828e203f0e74eefb
4
+ data.tar.gz: 5750d699b9cc98f47250893587ecf2b1f78e5dfc
5
5
  SHA512:
6
- metadata.gz: 62a1557f1ea417b35e2eb30bd723228b76206c24852ce1d996754ab650415214f35a607751b90e91c995957fd59fbb8a63a6d6ce12a55e81f38738d0db2e6424
7
- data.tar.gz: 93f4788d9ea0708a3214e5182a6495ad4bcb38075748fe591b2d2a3e6cad9138dcd4df55c71e59e5b9c605bfc0e4fb44da979b9c2220d818c9c7aece62896fe0
6
+ metadata.gz: aaf9b7fdbf3ce190129d084bd3340cdb3bc70cd295a2388e453025a76d19c3af5e9bb9ff4643db781b262be852acaa64cad5cc7ea124430ac471257f7d432348
7
+ data.tar.gz: 255682cbdf14cd3437ff53220ec476a02f2810143f039cee3eabeb80afa0fc0355fa7ec6cf7873b79af48d312a95c364d27b296bd34713dad3748efcd1dffdce
@@ -0,0 +1,2 @@
1
+ .bundle
2
+ Gemfile.lock
@@ -0,0 +1,4 @@
1
+ **Version 0.1.0** - *2017-01-04*
2
+
3
+ - :v and :vv options to err for more verbose output
4
+ - Fixed show command link replacement
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rerun'
7
+ gem 'rb-fsevent'
8
+ gem 'terminal-notifier'
9
+ end
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.
@@ -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`
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+ Bundler.require(:default, :development)
3
+
4
+ MODE = ENV['RACK_ENV'] || 'development'
5
+
6
+ require './lib/futest.rb'
7
+ require './models/model.rb'
@@ -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
@@ -1,3 +1,4 @@
1
+ require 'rest-client'
1
2
  require 'json'
2
3
 
3
4
  module Futest
@@ -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
@@ -0,0 +1,8 @@
1
+ class Model
2
+
3
+ attr_accessor :errors
4
+
5
+ def initialize
6
+ @errors = {}
7
+ end
8
+ end
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.0
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-04 00:00:00.000000000 Z
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