pry-test 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/pry-test +110 -0
- data/ext/mkrf_conf.rb +33 -0
- data/lib/pry-test.rb +5 -0
- data/lib/pry-test/formatters/base_formatter.rb +74 -0
- data/lib/pry-test/formatters/color.rb +26 -0
- data/lib/pry-test/formatters/default_async_formatter.rb +40 -0
- data/lib/pry-test/formatters/default_formatter.rb +24 -0
- data/lib/pry-test/formatters/template.rb +50 -0
- data/lib/pry-test/formatters/views/default/assert_fail.txt.erb +6 -0
- data/lib/pry-test/formatters/views/default/class.txt.erb +2 -0
- data/lib/pry-test/formatters/views/default/suite.txt.erb +9 -0
- data/lib/pry-test/formatters/views/default/test_fail.txt.erb +2 -0
- data/lib/pry-test/formatters/views/default/test_pass.txt.erb +1 -0
- data/lib/pry-test/formatters/views/default_async/test.txt.erb +1 -0
- data/lib/pry-test/runner.rb +73 -0
- data/lib/pry-test/test.rb +85 -0
- data/lib/pry-test/test_wrapper.rb +144 -0
- data/lib/pry-test/version.rb +3 -0
- data/test/color_test.rb +47 -0
- data/test/cpu_latency_test.rb +30 -0
- data/test/fail_test.rb +18 -0
- data/test/io_latency_test.rb +22 -0
- data/test/runner_test.rb +15 -0
- data/test/test_helper.rb +4 -0
- data/test/test_test.rb +70 -0
- data/test/test_wrapper_test.rb +19 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bff3b5b582f2d0f20a0638c8f2d22fe2c8f34328
|
4
|
+
data.tar.gz: f47f593420062049f74de02e4c33ede5406c680b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9fb57924837b12dea333bd4e62d98f65c504c29482b4f2e151eaa645f3f8e646d24f9e1f0ca19acd088d3a7a842390fcdbdae7f4b0024d6af6ba456a263d5a76
|
7
|
+
data.tar.gz: c97f1dc2c54058853a4aa3a2ebbf815a22ca5153184acca03a0cf26e6eac41823df4ad67e94feacf24afaf7c349d9a7cfb088181d0ddb933924fc155ccc8386d
|
data/bin/pry-test
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "optparse"
|
3
|
+
require_relative "../lib/pry-test"
|
4
|
+
|
5
|
+
include PryTest::Color
|
6
|
+
|
7
|
+
# setup the formatters list ---------------------------------------------------
|
8
|
+
formatter_names = PryTest.formatters.map(&:short_name).sort
|
9
|
+
|
10
|
+
# setup the options -----------------------------------------------------------
|
11
|
+
options = {}
|
12
|
+
parser = OptionParser.new do |opts|
|
13
|
+
opts.banner = "PryTest Usage: pry-test [options] /path/to/test/dir_or_file"
|
14
|
+
|
15
|
+
desc = "Runs tests asynchronously."
|
16
|
+
opts.on("-a", "--async", desc) { |value| options[:async] = value }
|
17
|
+
|
18
|
+
desc = "Runs the PryTest test suite and some additional demo tests."
|
19
|
+
opts.on("--demo", desc) { |value| options[:demo] = value }
|
20
|
+
|
21
|
+
desc = "The formatter to use. [#{formatter_names.join(", ")}]"
|
22
|
+
opts.on("-f", "--formatter [FORMATTER]", desc) do |value|
|
23
|
+
options[:formatter] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
desc = "Stops the test run after the first failure. "
|
27
|
+
opts.on("--fail-fast", desc) { |value| options[:fail_fast] = value }
|
28
|
+
|
29
|
+
desc = "Disabled pry during the test run. "
|
30
|
+
opts.on("--disable-pry", desc) { |value| options[:disable_pry] = value }
|
31
|
+
|
32
|
+
opts.on("-v", "--version", "Show version.") do
|
33
|
+
puts "PryTest #{PryTest::VERSION}"
|
34
|
+
exit 0
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on_tail("-h", "--help", "Show this message.") do
|
38
|
+
puts opts
|
39
|
+
exit 0
|
40
|
+
end
|
41
|
+
end
|
42
|
+
parser.parse!
|
43
|
+
|
44
|
+
ENV["MT_DEMO"] = "true" if options[:demo]
|
45
|
+
|
46
|
+
# setup the test path ---------------------------------------------------------
|
47
|
+
path = ARGV.last unless ARGV.last =~ /^-/
|
48
|
+
path = File.expand_path("../../test", __FILE__) if options[:demo]
|
49
|
+
path ||= "test"
|
50
|
+
path = File.join(Dir.pwd, path) unless path =~ /^\//
|
51
|
+
unless File.exist?(path)
|
52
|
+
puts "#{path} not found."
|
53
|
+
puts "Please check the path and try again."
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
if path =~ /\.rb$/
|
57
|
+
require path
|
58
|
+
else
|
59
|
+
Dir[File.join(path, "**/*.rb")].each { |path| require path }
|
60
|
+
end
|
61
|
+
|
62
|
+
# setup the formatter ---------------------------------------------------------
|
63
|
+
formatter = PryTest.formatters.find { |f| f.short_name == options[:formatter] }
|
64
|
+
formatter ||= begin
|
65
|
+
if options[:async]
|
66
|
+
PryTest.formatters.find { |f| f.short_name == "default_async" }
|
67
|
+
else
|
68
|
+
PryTest.formatters.find { |f| f.short_name == "default" }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# setup the test runner -------------------------------------------------------
|
73
|
+
runner = PryTest::Runner.new(formatter.new, options)
|
74
|
+
|
75
|
+
# setup pry -------------------------------------------------------------------
|
76
|
+
if options[:async] || RUBY_ENGINE == "jruby" || RUBY_ENGINE == "rbx"
|
77
|
+
optional[:disable_pry] = true
|
78
|
+
end
|
79
|
+
|
80
|
+
if options[:disable_pry]
|
81
|
+
puts magenta("Disabling pry when running with: [#{RUBY_ENGINE}] #{options.inspect}")
|
82
|
+
exit runner.run
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
require "pry"
|
86
|
+
require "pry-stack_explorer"
|
87
|
+
require "pry-rescue"
|
88
|
+
rescue Exception => e
|
89
|
+
puts red(e.message)
|
90
|
+
puts e.backtrace.join("\n")
|
91
|
+
puts red("This can be caused when pry-stack_explorer isn't specified in the Gemfile.")
|
92
|
+
puts red("It might also indicate that pry-stack_explorer & pry are out of sync.")
|
93
|
+
puts red("Try different cominations of GEM versions for pry & pry-stack_explorer.")
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
97
|
+
Pry.config.hooks.add_hook :before_session, :print_instructions do |_, _, _pry_|
|
98
|
+
puts
|
99
|
+
puts magenta(" Pry session started")
|
100
|
+
puts magenta("".ljust(80, "-"))
|
101
|
+
puts " #{magenta " Failures:"} Type #{green "up"} to see the line that failed"
|
102
|
+
puts " #{magenta "Exceptions:"} Type #{green "whereami"} to get your bearings"
|
103
|
+
puts
|
104
|
+
puts " Type #{green "exit"} or #{green "<CTL-D>"} to continue"
|
105
|
+
puts magenta("".ljust(80, "-"))
|
106
|
+
puts
|
107
|
+
end
|
108
|
+
|
109
|
+
exit Pry.rescue { runner.run }
|
110
|
+
end
|
data/ext/mkrf_conf.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# based on instructions here:
|
2
|
+
# http://en.wikibooks.org/wiki/Ruby_Programming/RubyGems#How_to_install_different_versions_of_gems_depending_on_which_version_of_ruby_the_installee_is_using
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/command.rb'
|
5
|
+
require 'rubygems/dependency_installer.rb'
|
6
|
+
|
7
|
+
begin
|
8
|
+
Gem::Command.build_args = ARGV
|
9
|
+
rescue NoMethodError
|
10
|
+
end
|
11
|
+
|
12
|
+
installer = Gem::DependencyInstaller.new
|
13
|
+
|
14
|
+
begin
|
15
|
+
if !(RUBY_ENGINE =~ /jruby/i)
|
16
|
+
puts "Installing pry and pry-stack_explorer."
|
17
|
+
installer.install "pry"
|
18
|
+
installer.install "pry-stack_explorer"
|
19
|
+
installer.install "pry-rescue"
|
20
|
+
else
|
21
|
+
puts "Platform is java... skip install for pry and pry-stack_explorer."
|
22
|
+
end
|
23
|
+
rescue Exception => e
|
24
|
+
puts e.message
|
25
|
+
puts e.backtrace.join("\n")
|
26
|
+
exit(1)
|
27
|
+
end
|
28
|
+
|
29
|
+
f = File.open(File.expand_path("../Rakefile", __FILE__), "w") # create dummy rakefile to indicate success
|
30
|
+
f.write("task :default\n")
|
31
|
+
f.close
|
32
|
+
|
33
|
+
exit
|
data/lib/pry-test.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module PryTest
|
2
|
+
|
3
|
+
class << self
|
4
|
+
def formatters
|
5
|
+
@formatters ||= []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# The base class for formatters.
|
10
|
+
# Defines the API that formatters can/should implement
|
11
|
+
# to control test run output.
|
12
|
+
class BaseFormatter
|
13
|
+
attr_accessor :passed, :failed, :duration
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def inherited(subclass)
|
17
|
+
PryTest.formatters << subclass
|
18
|
+
end
|
19
|
+
|
20
|
+
def short_name
|
21
|
+
@short_name || name
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_short_name(value)
|
25
|
+
@short_name = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@duration = 0
|
31
|
+
@passed = 0
|
32
|
+
@failed = 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def before_suite(test_classes)
|
36
|
+
end
|
37
|
+
|
38
|
+
def before_class(test_class)
|
39
|
+
end
|
40
|
+
|
41
|
+
def before_test(test)
|
42
|
+
end
|
43
|
+
|
44
|
+
def after_test(test)
|
45
|
+
end
|
46
|
+
|
47
|
+
def after_class(test_class)
|
48
|
+
end
|
49
|
+
|
50
|
+
def after_results(runner)
|
51
|
+
@duration = runner.duration
|
52
|
+
@passed = runner.passed
|
53
|
+
@failed = runner.failed
|
54
|
+
end
|
55
|
+
|
56
|
+
def after_suite(test_classes)
|
57
|
+
end
|
58
|
+
|
59
|
+
def render(template_name, template_context=nil)
|
60
|
+
puts text_to_render(template_name, template_context)
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_inline(template_name, template_context=nil)
|
64
|
+
print text_to_render(template_name, template_context)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def text_to_render(template_name, template_context=nil)
|
70
|
+
Template.new(template_context || self).render_to_string(template_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PryTest
|
2
|
+
module Color
|
3
|
+
extend self
|
4
|
+
|
5
|
+
colors = {
|
6
|
+
:red => 31,
|
7
|
+
:green => 32,
|
8
|
+
:yellow => 33,
|
9
|
+
:blue => 34,
|
10
|
+
:magenta => 35,
|
11
|
+
:cyan => 36,
|
12
|
+
:white => 37,
|
13
|
+
:gray => 90
|
14
|
+
}
|
15
|
+
|
16
|
+
def default(text)
|
17
|
+
text
|
18
|
+
end
|
19
|
+
|
20
|
+
colors.each do |name, code|
|
21
|
+
define_method name do |text|
|
22
|
+
"\e[#{code}m#{text}\e[0m"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "base_formatter"
|
2
|
+
|
3
|
+
module PryTest
|
4
|
+
class DefaultAsyncFormatter < PryTest::BaseFormatter
|
5
|
+
set_short_name "default_async"
|
6
|
+
|
7
|
+
def after_test(test)
|
8
|
+
render_inline "default_async/test", test
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_suite(test_classes)
|
12
|
+
puts
|
13
|
+
test_classes.each do |test_class|
|
14
|
+
render_output_for_test_class test_class
|
15
|
+
end
|
16
|
+
|
17
|
+
render "default/suite"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def render_output_for_test_class(test_class)
|
23
|
+
render "default/class", test_class
|
24
|
+
test_class.tests.each do |test|
|
25
|
+
render_output_for_test test
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_output_for_test(test)
|
30
|
+
return unless test.finished?
|
31
|
+
|
32
|
+
if test.passed?
|
33
|
+
render "default/test_pass", test
|
34
|
+
else
|
35
|
+
render "default/test_fail", test
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative "base_formatter"
|
2
|
+
|
3
|
+
module PryTest
|
4
|
+
class DefaultFormatter < PryTest::BaseFormatter
|
5
|
+
set_short_name "default"
|
6
|
+
|
7
|
+
def before_class(test_class)
|
8
|
+
render "default/class", test_class
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_test(test)
|
12
|
+
if test.passed?
|
13
|
+
render "default/test_pass", test
|
14
|
+
else
|
15
|
+
render "default/test_fail", test
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_suite(test_classes)
|
20
|
+
render "default/suite"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative "color"
|
2
|
+
|
3
|
+
module PryTest
|
4
|
+
class Template
|
5
|
+
include Color
|
6
|
+
|
7
|
+
def self.view(name)
|
8
|
+
@views ||= {}
|
9
|
+
@views[name] ||= File.read(File.expand_path("../views/#{name}.txt.erb", __FILE__))
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(context)
|
13
|
+
@context = context
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_to_string(name)
|
17
|
+
instance_eval do
|
18
|
+
ERB.new(self.class.view(name), nil, "%<>-").result(binding)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def partial(name, *collection)
|
23
|
+
return render_to_string(name) if collection.empty?
|
24
|
+
collection.map do |item|
|
25
|
+
Template.new(item).render_to_string(name)
|
26
|
+
end.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def duration_color(duration)
|
30
|
+
return :yellow if @context.duration <= 0.01
|
31
|
+
:red
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_lines(assert)
|
35
|
+
index = assert[:line_num] - 1
|
36
|
+
start = index - 2
|
37
|
+
start = 0 if start <= 0
|
38
|
+
finish = index + 2
|
39
|
+
finish = assert[:lines].length - 1 if finish >= assert[:lines].length
|
40
|
+
(start..finish).map do |i|
|
41
|
+
{
|
42
|
+
:line_num => (i + 1),
|
43
|
+
:line => assert[:lines][i],
|
44
|
+
:color => (i == index ? :red : :gray)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<%= @context[:file_path].strip %><%= gray ":" %><%= red @context[:line_num] %>
|
2
|
+
<%= red "".ljust(80, "-") %>
|
3
|
+
<% assert_lines(@context).each do |line| -%>
|
4
|
+
<%= send line[:color], line[:line_num].to_s.rjust(4) %><%= gray "|" %> <%= send line[:color], line[:line] -%>
|
5
|
+
<% end -%>
|
6
|
+
<%= red "".ljust(80, "-") %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
|
2
|
+
--------------------------------------------------------------------------------
|
3
|
+
<%= green "#{@context.passed} Passed" -%>
|
4
|
+
<% if @context.failed > 0 -%>
|
5
|
+
, <%= red "#{@context.failed} Failed" -%>
|
6
|
+
<% end -%>
|
7
|
+
Finished in <%= yellow @context.duration %> seconds.
|
8
|
+
--------------------------------------------------------------------------------
|
9
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= send duration_color(@context.duration), @context.duration %> <%= green @context.desc -%>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= gray "." -%>
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "os"
|
2
|
+
require "thread"
|
3
|
+
|
4
|
+
module PryTest
|
5
|
+
class Runner
|
6
|
+
class << self
|
7
|
+
attr_accessor :exit
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :formatter, :options, :active_test, :duration, :passed, :failed
|
11
|
+
|
12
|
+
def initialize(formatter, options={})
|
13
|
+
@formatter = formatter
|
14
|
+
@options = options
|
15
|
+
reset
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
test_classes = PryTest::Test.subclasses.shuffle
|
20
|
+
tests = test_classes.map{ |klass| klass.tests }.flatten
|
21
|
+
formatter.before_suite(test_classes)
|
22
|
+
start = Time.now
|
23
|
+
|
24
|
+
test_classes.each do |test_class|
|
25
|
+
formatter.before_class(test_class)
|
26
|
+
test_class.tests.shuffle.each do |test|
|
27
|
+
@active_test = test
|
28
|
+
if @options[:async]
|
29
|
+
@tests ||= Queue.new
|
30
|
+
@tests << test
|
31
|
+
else
|
32
|
+
test.invoke(@formatter, @options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
formatter.after_class(test_class)
|
36
|
+
end
|
37
|
+
|
38
|
+
run_threads if @options[:async]
|
39
|
+
|
40
|
+
@duration = Time.now - start
|
41
|
+
@passed = tests.select{ |test| test.passed? }.count
|
42
|
+
@failed = tests.select{ |test| !test.passed? }.count
|
43
|
+
formatter.after_results(self)
|
44
|
+
formatter.after_suite(test_classes)
|
45
|
+
@failed
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset
|
49
|
+
@duration = 0
|
50
|
+
@passed = 0
|
51
|
+
@failed = 0
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def run_threads
|
57
|
+
threads = []
|
58
|
+
thread_count = OS.cpu_count
|
59
|
+
thread_count = 2 if thread_count < 2
|
60
|
+
puts "PryTest is running #{thread_count} threads."
|
61
|
+
thread_count.times do
|
62
|
+
threads << Thread.new do
|
63
|
+
while @tests.empty? == false
|
64
|
+
Thread.current.kill if PryTest::Runner.exit
|
65
|
+
@tests.pop.invoke(@formatter, @options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
threads.each { |t| t.join }
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module PryTest
|
2
|
+
|
3
|
+
# Superclass for all test classes.
|
4
|
+
# @example Create a subclass with a test.
|
5
|
+
# class SimpleTest < PryTest::Test
|
6
|
+
# test "common sense" do
|
7
|
+
# assert 1 > 0
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
class Test
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# All subclasses of this class.
|
14
|
+
# @return [Array<PryTest::Test>]
|
15
|
+
def subclasses
|
16
|
+
@subclasses ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
# All individual tests defined in this class.
|
20
|
+
# @return [Array<PryTest::TestWrapper>]
|
21
|
+
def tests
|
22
|
+
@tests ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
# All files that define subclasses of this class.
|
26
|
+
# @note Primarily used in the context of PryTest::Test.
|
27
|
+
# @example Files are stored in a Hash with the following format.
|
28
|
+
# {
|
29
|
+
# "path/to/file1.rb" => ["line 1", "line 2", "line 3", ...],
|
30
|
+
# "path/to/file2.rb" => ["line 1", "line 2", "line 3", ...]
|
31
|
+
# }
|
32
|
+
# @return [Hash]
|
33
|
+
def files
|
34
|
+
@files ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Resets the state in preparation for a new test run.
|
38
|
+
def reset
|
39
|
+
tests.each { |test| test.reset }
|
40
|
+
subclasses.each { |subclass| subclass.reset }
|
41
|
+
end
|
42
|
+
|
43
|
+
# A callback provided by Ruby that is invoked whenever a subclass is created.
|
44
|
+
def inherited(subclass)
|
45
|
+
file_path = caller[0][0, caller[0].index(/:[0-9]+:/)]
|
46
|
+
files[file_path] = File.open(file_path).readlines
|
47
|
+
subclasses << subclass
|
48
|
+
end
|
49
|
+
|
50
|
+
# Defines a setup method that will run before each individual test.
|
51
|
+
# @param [Symbol] what Deprecated but maintained for backwards compatibility.
|
52
|
+
# @yield A block of code that will serve as the setup method.
|
53
|
+
def before(what=nil, &block)
|
54
|
+
@before = block
|
55
|
+
end
|
56
|
+
|
57
|
+
# Defines a teardown method that will run after each individual test.
|
58
|
+
# @param [Symbol] what Deprecated but maintained for backwards compatibility.
|
59
|
+
# @yield A block of code that will serve as the teardown method.
|
60
|
+
def after(what=nil, &block)
|
61
|
+
@after = block
|
62
|
+
end
|
63
|
+
|
64
|
+
# Defines a test.
|
65
|
+
# Allows subclasses to define tests in their class definition.
|
66
|
+
#
|
67
|
+
# @param [String] desc A description for the test.
|
68
|
+
# @yield A block that defines the test code.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# class SimpleTest < PryTest::Test
|
72
|
+
# test "common sense" do
|
73
|
+
# assert 1 > 0
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
def test(desc, &block)
|
77
|
+
wrapper = PryTest::TestWrapper.new(self, desc, &block)
|
78
|
+
wrapper.create_method(:before, &@before) if @before
|
79
|
+
wrapper.create_method(:after, &@after) if @after
|
80
|
+
tests << wrapper
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require "monitor"
|
2
|
+
|
3
|
+
module PryTest
|
4
|
+
|
5
|
+
# A wrapper class for individual tests.
|
6
|
+
# Exists for the purpose of isolating the test method so it can run in its own thread.
|
7
|
+
class TestWrapper
|
8
|
+
include MonitorMixin
|
9
|
+
attr_reader :test_class, :desc, :asserts
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
# @param [PryTest::Test] test_class The test class that defines the test being wrapped.
|
13
|
+
# @param [String] desc The test description.
|
14
|
+
# @yield The block that defines the test code.
|
15
|
+
def initialize(test_class, desc, &block)
|
16
|
+
super() # inits MonitorMixin
|
17
|
+
@test_class = test_class
|
18
|
+
@desc = desc
|
19
|
+
create_method(:test, &block)
|
20
|
+
reset
|
21
|
+
end
|
22
|
+
|
23
|
+
# Creates a method on this instance.
|
24
|
+
# @param [Symbol] name The name of the method.
|
25
|
+
# @yield The block of code that will serve as the method's implementation.
|
26
|
+
def create_method(name, &block)
|
27
|
+
eigen = class << self; self; end
|
28
|
+
eigen.send(:define_method, name, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
# callback stubs
|
32
|
+
def before; end
|
33
|
+
def after; end
|
34
|
+
|
35
|
+
# Runs the test code.
|
36
|
+
# @formatter [PryTest::Formatter] The formatter to use.
|
37
|
+
# @options [Hash]
|
38
|
+
def invoke(formatter, options={})
|
39
|
+
reset
|
40
|
+
@formatter = formatter
|
41
|
+
@options = options
|
42
|
+
@formatter.before_test(self)
|
43
|
+
start = Time.now
|
44
|
+
before
|
45
|
+
test
|
46
|
+
@invoked = true
|
47
|
+
after
|
48
|
+
@duration = Time.now - start
|
49
|
+
@formatter.after_test(self)
|
50
|
+
end
|
51
|
+
|
52
|
+
# A basic assert method to be used within tests.
|
53
|
+
#
|
54
|
+
# @param [Object] value The value to assert.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# class SimpleTest < PryTest::Test
|
58
|
+
# test "common sense" do
|
59
|
+
# assert 1 > 0
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
def assert(value)
|
63
|
+
@asserts << assert_info(caller).merge(:value => value)
|
64
|
+
|
65
|
+
if !value
|
66
|
+
binding.pry(:quiet => true) unless @options[:disable_pry]
|
67
|
+
|
68
|
+
# I don't really like the coupling to the runner here
|
69
|
+
PryTest::Runner.exit = true if @options[:fail_fast]
|
70
|
+
end
|
71
|
+
|
72
|
+
value
|
73
|
+
end
|
74
|
+
|
75
|
+
# Indicates if this test has finished running.
|
76
|
+
# @return [Boolean]
|
77
|
+
def finished?
|
78
|
+
!@duration.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Indicates if this test passed.
|
82
|
+
def passed?
|
83
|
+
return true if !@invoked || @asserts.empty?
|
84
|
+
return false if @asserts.empty?
|
85
|
+
@asserts.map{ |a| !!a[:value] }.uniq == [true]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns a list of all failed asserts.
|
89
|
+
def failed_asserts
|
90
|
+
return [] if passed?
|
91
|
+
@asserts.select { |a| !a[:value] }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Resets this test in preparation for a clean test run.
|
95
|
+
def reset
|
96
|
+
@invoked = false
|
97
|
+
@asserts = []
|
98
|
+
@duration = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
# Rounded duration.
|
102
|
+
def duration
|
103
|
+
return nil if @duration.nil?
|
104
|
+
(@duration * 10**4).ceil.to_f / 10**4
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# Builds a Hash of assert information for the given call stack.
|
110
|
+
#
|
111
|
+
# @param [Array<String>] stack The call stack to extract info from.
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# {
|
115
|
+
# :file_path => "/path/to/test_file.rb",
|
116
|
+
# :line_num => 100,
|
117
|
+
# :line => " assert 'something' do"
|
118
|
+
# }
|
119
|
+
#
|
120
|
+
# @return [Hash]
|
121
|
+
def assert_info(stack)
|
122
|
+
file_path = stack[0][0, stack[0].index(/:[0-9]+:/)]
|
123
|
+
lines = PryTest::Test.files[file_path]
|
124
|
+
line_num = line_number(stack, 0)
|
125
|
+
line_index = line_num - 1
|
126
|
+
line = lines[line_index]
|
127
|
+
{
|
128
|
+
:file_path => file_path,
|
129
|
+
:lines => lines,
|
130
|
+
:line_num => line_num,
|
131
|
+
:line => line
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns a line number from a call stack.
|
136
|
+
# @param [Array<String>] stack The call stack to pull a path from.
|
137
|
+
# @param [Integer] index The index of the call stack entry to use.
|
138
|
+
# @return [String]
|
139
|
+
def line_number(stack, index)
|
140
|
+
stack[index].scan(/:[0-9]+:/).first.gsub(/:/, "").to_i
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
data/test/color_test.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
unless ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class ColorTest < PryTest::Test
|
5
|
+
class Crayon
|
6
|
+
include PryTest::Color
|
7
|
+
end
|
8
|
+
CRAYON = Crayon.new
|
9
|
+
|
10
|
+
test "red" do
|
11
|
+
assert PryTest::Color.red("foo") == "\e[31mfoo\e[0m"
|
12
|
+
assert ColorTest::CRAYON.red("foo") == "\e[31mfoo\e[0m"
|
13
|
+
end
|
14
|
+
|
15
|
+
test "green" do
|
16
|
+
assert PryTest::Color.green("foo") == "\e[32mfoo\e[0m"
|
17
|
+
assert ColorTest::CRAYON.green("foo") == "\e[32mfoo\e[0m"
|
18
|
+
end
|
19
|
+
|
20
|
+
test "yellow" do
|
21
|
+
assert PryTest::Color.yellow("foo") == "\e[33mfoo\e[0m"
|
22
|
+
assert ColorTest::CRAYON.yellow("foo") == "\e[33mfoo\e[0m"
|
23
|
+
end
|
24
|
+
|
25
|
+
test "blue" do
|
26
|
+
assert PryTest::Color.blue("foo") == "\e[34mfoo\e[0m"
|
27
|
+
assert ColorTest::CRAYON.blue("foo") == "\e[34mfoo\e[0m"
|
28
|
+
end
|
29
|
+
|
30
|
+
test "magenta" do
|
31
|
+
assert PryTest::Color.magenta("foo") == "\e[35mfoo\e[0m"
|
32
|
+
assert ColorTest::CRAYON.magenta("foo") == "\e[35mfoo\e[0m"
|
33
|
+
end
|
34
|
+
|
35
|
+
test "cyan" do
|
36
|
+
assert PryTest::Color.cyan("foo") == "\e[36mfoo\e[0m"
|
37
|
+
assert ColorTest::CRAYON.cyan("foo") == "\e[36mfoo\e[0m"
|
38
|
+
end
|
39
|
+
|
40
|
+
test "white" do
|
41
|
+
assert PryTest::Color.white("foo") == "\e[37mfoo\e[0m"
|
42
|
+
assert ColorTest::CRAYON.white("foo") == "\e[37mfoo\e[0m"
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
if ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class TestCPULatency < PryTest::Test
|
5
|
+
|
6
|
+
before do
|
7
|
+
@count = 35
|
8
|
+
end
|
9
|
+
|
10
|
+
test "fibonacci recursion 1" do
|
11
|
+
@count.times { |i| TestCPULatency.fib(i) }
|
12
|
+
assert true
|
13
|
+
end
|
14
|
+
|
15
|
+
test "fibonacci recursion 2" do
|
16
|
+
@count.times { |i| TestCPULatency.fib(i) }
|
17
|
+
assert true
|
18
|
+
end
|
19
|
+
|
20
|
+
test "fibonacci recursion 3" do
|
21
|
+
@count.times { |i| TestCPULatency.fib(i) }
|
22
|
+
assert true
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fib(n)
|
26
|
+
n < 2 ? n : fib(n-1) + fib(n-2)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/test/fail_test.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
if ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class Fail < PryTest::Test
|
5
|
+
|
6
|
+
before do
|
7
|
+
@var = "fubar"
|
8
|
+
end
|
9
|
+
|
10
|
+
test "fail on purpose" do
|
11
|
+
# Failing on purpose for the demo.
|
12
|
+
# Use pry to check out the current binding.
|
13
|
+
# For example, type @var.
|
14
|
+
assert false
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
if ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class TestIOLatency < PryTest::Test
|
5
|
+
|
6
|
+
test "sleep 1 sec" do
|
7
|
+
sleep 1
|
8
|
+
assert true
|
9
|
+
end
|
10
|
+
|
11
|
+
test "sleep another 1 sec" do
|
12
|
+
sleep 1
|
13
|
+
assert true
|
14
|
+
end
|
15
|
+
|
16
|
+
test "sleep a third 1 sec" do
|
17
|
+
sleep 1
|
18
|
+
assert true
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/test/runner_test.rb
ADDED
data/test/test_helper.rb
ADDED
data/test/test_test.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
unless ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class TestTest < PryTest::Test
|
5
|
+
|
6
|
+
before do
|
7
|
+
@test_test = TestTest.clone
|
8
|
+
@test_test.instance_eval { @subclasses = [] }
|
9
|
+
@test_test.instance_eval { @tests = [] }
|
10
|
+
@Example = Class.new(@test_test) do
|
11
|
+
before {}
|
12
|
+
after {}
|
13
|
+
test("truth") { assert true }
|
14
|
+
end
|
15
|
+
@before_callback = @Example.before
|
16
|
+
@after_callback = @Example.after
|
17
|
+
end
|
18
|
+
|
19
|
+
test "adds subclass" do
|
20
|
+
assert @test_test.subclasses.length == 1
|
21
|
+
assert @test_test.subclasses[0] == @Example
|
22
|
+
end
|
23
|
+
|
24
|
+
test "stores subclasses" do
|
25
|
+
assert @test_test.subclasses.is_a?(Array)
|
26
|
+
assert @test_test.subclasses.length == 1
|
27
|
+
assert @test_test.subclasses.first == @Example
|
28
|
+
end
|
29
|
+
|
30
|
+
test "stores tests" do
|
31
|
+
assert @Example.tests.is_a?(Array)
|
32
|
+
assert @Example.tests.length == 1
|
33
|
+
assert @Example.tests.first.is_a?(PryTest::TestWrapper)
|
34
|
+
end
|
35
|
+
|
36
|
+
test "stores files" do
|
37
|
+
file = __FILE__
|
38
|
+
assert @test_test.files[file].is_a?(Array)
|
39
|
+
assert @test_test.files[file].select{ |l| l.start_with?(" assert @test_test.files[file].select{ |l| l.start_with?(") }.length > 0
|
40
|
+
end
|
41
|
+
|
42
|
+
test ".reset" do
|
43
|
+
@Example.tests.first.instance_eval do
|
44
|
+
@asserts = nil
|
45
|
+
@duration = nil
|
46
|
+
end
|
47
|
+
@Example.reset
|
48
|
+
assert @Example.tests.length == 1
|
49
|
+
assert @Example.tests.first.asserts == []
|
50
|
+
assert @Example.tests.first.duration == nil
|
51
|
+
end
|
52
|
+
|
53
|
+
test ".before" do
|
54
|
+
assert @Example.instance_eval { @before } == @before_callback
|
55
|
+
end
|
56
|
+
|
57
|
+
test ".after" do
|
58
|
+
assert @Example.instance_eval { @after } == @after_callback
|
59
|
+
end
|
60
|
+
|
61
|
+
test "tests" do
|
62
|
+
t = lambda {}
|
63
|
+
@Example.send :test, :add_a_test, &t
|
64
|
+
assert @Example.tests.length == 2
|
65
|
+
assert @Example.tests.last.is_a?(PryTest::TestWrapper)
|
66
|
+
assert @Example.tests.last.desc == :add_a_test
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
unless ENV["MT_DEMO"]
|
2
|
+
require_relative "test_helper"
|
3
|
+
|
4
|
+
class TestWrapperTest < PryTest::Test
|
5
|
+
|
6
|
+
test ".new" do
|
7
|
+
desc = "test_#{rand(999**10)}"
|
8
|
+
meth = lambda { ".new" }
|
9
|
+
t = PryTest::TestWrapper.new(TestWrapperTest, desc, &meth)
|
10
|
+
assert t.desc == desc
|
11
|
+
assert t.test == ".new"
|
12
|
+
assert t.passed?
|
13
|
+
assert t.finished? == false
|
14
|
+
assert t.duration.nil?
|
15
|
+
assert t.asserts.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pry-test
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Hopkins
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: os
|
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: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: coveralls
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A testing framework that supports debugging test failures & errors as
|
56
|
+
they happen.
|
57
|
+
email:
|
58
|
+
- natehop@gmail.com
|
59
|
+
executables:
|
60
|
+
- pry-test
|
61
|
+
extensions:
|
62
|
+
- ext/mkrf_conf.rb
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- bin/pry-test
|
66
|
+
- ext/mkrf_conf.rb
|
67
|
+
- lib/pry-test.rb
|
68
|
+
- lib/pry-test/formatters/base_formatter.rb
|
69
|
+
- lib/pry-test/formatters/color.rb
|
70
|
+
- lib/pry-test/formatters/default_async_formatter.rb
|
71
|
+
- lib/pry-test/formatters/default_formatter.rb
|
72
|
+
- lib/pry-test/formatters/template.rb
|
73
|
+
- lib/pry-test/formatters/views/default/assert_fail.txt.erb
|
74
|
+
- lib/pry-test/formatters/views/default/class.txt.erb
|
75
|
+
- lib/pry-test/formatters/views/default/suite.txt.erb
|
76
|
+
- lib/pry-test/formatters/views/default/test_fail.txt.erb
|
77
|
+
- lib/pry-test/formatters/views/default/test_pass.txt.erb
|
78
|
+
- lib/pry-test/formatters/views/default_async/test.txt.erb
|
79
|
+
- lib/pry-test/runner.rb
|
80
|
+
- lib/pry-test/test.rb
|
81
|
+
- lib/pry-test/test_wrapper.rb
|
82
|
+
- lib/pry-test/version.rb
|
83
|
+
- test/color_test.rb
|
84
|
+
- test/cpu_latency_test.rb
|
85
|
+
- test/fail_test.rb
|
86
|
+
- test/io_latency_test.rb
|
87
|
+
- test/runner_test.rb
|
88
|
+
- test/test_helper.rb
|
89
|
+
- test/test_test.rb
|
90
|
+
- test/test_wrapper_test.rb
|
91
|
+
homepage: https://github.com/hopsoft/pry-test
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.9.2
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.2.2
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: A testing framework that supports debugging test failures & errors as they
|
115
|
+
happen.
|
116
|
+
test_files:
|
117
|
+
- test/color_test.rb
|
118
|
+
- test/cpu_latency_test.rb
|
119
|
+
- test/fail_test.rb
|
120
|
+
- test/io_latency_test.rb
|
121
|
+
- test/runner_test.rb
|
122
|
+
- test/test_helper.rb
|
123
|
+
- test/test_test.rb
|
124
|
+
- test/test_wrapper_test.rb
|