rcheck 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db2b815fb1dba30c7de1c16a7c01f889e0743136
4
+ data.tar.gz: 085cedf81b658fad89957c4fb5cef098d29bdac6
5
+ SHA512:
6
+ metadata.gz: f6e9311dfe285e0a3762e92c2c30705ae0e7892350806066afb02f5044a73d2e5eccdce82e7832b03c0d4f1ce9a7b9f1ca8c3fbed3c705125add28bd41e7ab6a
7
+ data.tar.gz: 07fcfc75690e0b841dd9c9ad0093bb2344f540959ddc173d81d76f50028f055a8bbf77092f53ff89775cd032f0f45272cf01428427f9ec2443e854687abe5f6f
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in the gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rcheck (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.0)
10
+ method_source (0.8.2)
11
+ pry (0.10.2)
12
+ coderay (~> 1.1.0)
13
+ method_source (~> 0.8.1)
14
+ slop (~> 3.4)
15
+ rake (10.4.2)
16
+ slop (3.6.0)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 1.10)
23
+ pry
24
+ rake (~> 10.0)
25
+ rcheck!
26
+
27
+ BUNDLED WITH
28
+ 1.10.6
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ ## RCheck
2
+
3
+ Easier and faster tests
4
+
5
+ ---
6
+
7
+ Work in progress.
8
+
9
+ To get started:
10
+
11
+ - See the `/test` directory
12
+ - `rake install`
13
+ - `rcheck usage`
14
+ - `rcheck help`
15
+
16
+ ---
17
+
18
+ Copyright © 2015 Jostein Berre Eliassen
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining
21
+ a copy of this software and associated documentation files (the "Software"),
22
+ to deal in the Software without restriction, including without limitation
23
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
24
+ and/or sell copies of the Software, and to permit persons to whom the
25
+ Software is furnished to do so, subject to the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be included
28
+ in all copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
32
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
34
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
35
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
36
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task default: "test:all"
4
+
5
+ def setup
6
+ require 'bundler/setup'
7
+ require 'rcheck'
8
+ end
9
+
10
+
11
+ namespace :test do
12
+ desc 'Run all tests'
13
+ task :all do
14
+ setup
15
+ RCheck.invoke!
16
+ end
17
+
18
+ namespace :sanity do
19
+ task :axioms do
20
+ RCheck.invoke! suite: 'RCheck/sanity/axioms'
21
+ end
22
+ end
23
+
24
+ namespace :generate do
25
+ task :html do
26
+ setup
27
+ RCheck.invoke! :silent, :html
28
+ end
29
+ end
30
+ end
31
+
32
+ desc 'Open interactive console'
33
+ task :console do
34
+ setup
35
+ require 'pry'
36
+ Pry.start
37
+ end
data/TODO ADDED
@@ -0,0 +1,20 @@
1
+
2
+ # TODO:
3
+
4
+ Option
5
+ #parse
6
+ #format
7
+
8
+
9
+ # - show #debug lines when something fails
10
+ # - new error names
11
+ # - include seed in dsl
12
+ # - remove spec location lines from trace == genius
13
+ # - self tests, cleanup, overview
14
+ # - field test, are spec locations safe?
15
+ # - readme
16
+ # - homepage
17
+
18
+ # Remote possibilities:
19
+ # - profiler
20
+ # - coverage
data/bin/rcheck ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'rcheck/cli'
5
+ rescue LoadError
6
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
7
+ require 'rcheck/cli'
8
+ end
9
+
10
+ RCheck::CLI.new(ARGV).invoke!
data/lib/rcheck.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'forwardable'
2
+
3
+ # base:
4
+ require 'rcheck/version'
5
+ require 'rcheck/errors'
6
+ require 'rcheck/backtrace'
7
+ require 'rcheck/formatting'
8
+ require 'rcheck/result'
9
+ require 'rcheck/assertions'
10
+ require 'rcheck/debugging'
11
+ require 'rcheck/suite'
12
+ require 'rcheck/dsl'
13
+
14
+ # configuration and running:
15
+ require 'rcheck/options'
16
+ require 'rcheck/option_expander'
17
+ require 'rcheck/command'
18
+ require 'rcheck/conf'
19
+
20
+ # pluggable by configuration:
21
+ require 'rcheck/colors'
22
+ require 'rcheck/filters'
23
+ require 'rcheck/progress_printers'
24
+ require 'rcheck/report_printers'
25
+ require 'rcheck/headers'
26
+
27
+ require 'rcheck/class_methods'
28
+
29
+ module RCheck
30
+ extend ClassMethods
31
+ ROOT_SUITE = Suite.new(nil, nil)
32
+ USER_CONF = File.join Dir.home, '.rcheck'
33
+ require USER_CONF if File.file?(USER_CONF + '.rb')
34
+ end
35
+
36
+ require 'rcheck/default_commands'
37
+
38
+ def RCheck(*args, &blk)
39
+ RCheck.suite(*args, &blk)
40
+ end
@@ -0,0 +1,122 @@
1
+
2
+
3
+ module RCheck
4
+ module Assertions
5
+ module SuiteMethods
6
+
7
+ def assert(*args)
8
+ verify_not_done!
9
+ @assertions << Assert.new(*args)
10
+ end
11
+
12
+ def refute(*args)
13
+ verify_not_done!
14
+ @assertions << Refute.new(*args)
15
+ end
16
+
17
+ def assert_raises(*args, &blk)
18
+ verify_not_done!
19
+ @assertions << Raises.new(*args, &blk)
20
+ end
21
+
22
+ def assert_safe(&blk)
23
+ verify_not_done!
24
+ @assertions << Raises.new(nil, &blk)
25
+ end
26
+
27
+ def pending(*args)
28
+ verify_not_done!
29
+ @assertions << Pending.new(*args)
30
+ end
31
+ end
32
+
33
+ class Abstract
34
+ attr_reader :result
35
+
36
+ def inspect
37
+ "#<#{self.class.name}: #{status}>"
38
+ end
39
+
40
+ def debuggers
41
+ @debuggers ||= []
42
+ end
43
+ end
44
+
45
+ class Pending < Abstract
46
+ def initialize(desc=nil)
47
+ @result = Result.new(
48
+ introspection: desc,
49
+ status: :pending,
50
+ location: caller(3))
51
+ end
52
+ end
53
+
54
+ class AbstractAssert < Abstract
55
+ def initialize(left, op=nil, *right)
56
+ @left = left
57
+ @op = op
58
+ @right = right
59
+ @truth = (@right.empty? && @op.nil?) ?
60
+ @left : @left.send(@op, *@right)
61
+
62
+ @result = Result.new(
63
+ status: !!@truth != !!@refute ? :pass : :fail,
64
+ location: caller(4),
65
+ introspection: introspection)
66
+ end
67
+
68
+ private
69
+ def introspection
70
+ args = @right.map(&:inspect).join(', ')
71
+ @left.inspect + case @op
72
+ when *%i(== === < > <= >= ~= <=>) then " #{@op} #{args}"
73
+ when :[] then "[#{args}]"
74
+ when :[]=
75
+ "[#{@right.first.inspect}] = "\
76
+ "#{@right[1..-1].map(&:inspect).join(', ')}"
77
+ when nil then ''
78
+ else ".#{@op.to_s} #{args}"
79
+ end + " # #{@truth.inspect}"
80
+ # TODO: only show comment if different from introspection
81
+ end
82
+ end
83
+
84
+ class Assert < AbstractAssert
85
+ # TODO: use self.is_a? instead
86
+ def initialize(*args)
87
+ @refute = false
88
+ super
89
+ end
90
+ end
91
+
92
+ class Refute < AbstractAssert
93
+ def initialize(*args)
94
+ @refute = true
95
+ super
96
+ end
97
+ end
98
+
99
+ class Raises < Abstract
100
+ def initialize(expected, msg=nil, &blk)
101
+ @expected = expected
102
+ @expected_msg = msg
103
+ @status = :fail
104
+ begin
105
+ blk.call
106
+ rescue Exception => e
107
+ @raised = e
108
+ if @expected && e.is_a?(@expected) && (msg.nil? || e.message == msg)
109
+ @status = :pass
110
+ end
111
+ end
112
+ @status = :pass if @expected.nil? and @raised.nil?
113
+
114
+ @result = Result.new(
115
+ status: @status,
116
+ location: caller(3),
117
+ introspection: @raised ? @raised.inspect : 'no errors',
118
+ backtrace: @status == :fail ? @raised.backtrace : nil)
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,39 @@
1
+ require 'pathname'
2
+
3
+ module RCheck
4
+ module Backtrace
5
+ def self.parse(lines)
6
+ lines.reject do |line|
7
+ Conf[:filters].any? { |f| f.match(line) } and
8
+ !Conf[:anti_filters].any? { |f| f.match(line) }
9
+ end.map { |str| Line.new str }
10
+ end
11
+
12
+ class Line
13
+ attr_reader(*%i(file line))
14
+ def initialize(str)
15
+ @file, @line, @scope = str.split(':')
16
+ @line = line.to_i
17
+ @file = Pathname.new(File.expand_path(file)).
18
+ relative_path_from Pathname.new(Dir.pwd)
19
+ end
20
+
21
+ def short
22
+ "#{@file}:#{@line}"
23
+ end
24
+
25
+ def scope
26
+ @scope[4..-2]
27
+ end
28
+
29
+ def to_s
30
+ "%-30s %s" % [short, scope]
31
+ end
32
+
33
+ def source
34
+ src = File.readlines(File.expand_path(@file))[@line-1]
35
+ src && src.strip
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ module RCheck
2
+ module ClassMethods
3
+ extend Forwardable
4
+
5
+ def root() RCheck::ROOT_SUITE end
6
+
7
+ def_delegators(:root, *%i(suite [] severity))
8
+ def_delegators(Command, *%i(define invoke!))
9
+
10
+ def version
11
+ "RCheck #{VERSION} @ Ruby #{RUBY_VERSION}"
12
+ end
13
+
14
+ def which
15
+ File.expand_path('../../..', __FILE__)
16
+ end
17
+ end
18
+ end
data/lib/rcheck/cli.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'rcheck'
2
+ require 'rcheck/trollop'
3
+
4
+ module RCheck
5
+ class CLI
6
+ TROLLOP = Trollop::Parser.new do
7
+ banner 'Usage: rcheck [COMMANDS..] [OPTIONS..]'
8
+ banner "Example: rcheck list --files tests/thing.rb --seed 3276"
9
+ banner ''
10
+ banner "Commands:"
11
+ Command.available.each do |cmd|
12
+ banner "%10s #{cmd.desc}" % [cmd.name]
13
+ end
14
+ banner ''
15
+ banner 'Options:'
16
+ version VERSION
17
+ Options.defaults.each do |k, v|
18
+ opt k, Options::HELP[k], :default => v
19
+ end
20
+ end
21
+
22
+ def initialize(argv)
23
+ parse_commands(argv)
24
+ parse_options(argv)
25
+ end
26
+
27
+ def invoke!
28
+ RCheck.invoke!(*@commands, @options)
29
+ rescue Errors::Base => e
30
+ puts e.inspect
31
+ exit 1
32
+ end
33
+
34
+ private
35
+ def parse_commands(argv)
36
+ @commands = []
37
+ until argv.empty? || argv.first.start_with?('-')
38
+ @commands << argv.shift
39
+ end
40
+ @commands = @commands.map(&:to_sym)
41
+ end
42
+
43
+ def parse_options(argv)
44
+ @options = argv.any? ?
45
+ (Trollop::with_standard_exception_handling TROLLOP do
46
+ TROLLOP.parse(argv) # welcome to the syntax sandwich
47
+ end) : {}
48
+ @options.each_key do |name|
49
+ @options.delete name unless name.to_s.end_with?('_given') ||
50
+ @options[:"#{name.to_s}_given"]
51
+ end
52
+ @options.each_key do |name|
53
+ @options.delete name if name.to_s.end_with?('_given')
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+
2
+ module RCheck
3
+ module Colors
4
+ ESC = {
5
+ red: "\e[31m",
6
+ green: "\e[32m",
7
+ yellow: "\e[33m",
8
+ blue: "\e[34m",
9
+ magenta: "\e[35m",
10
+ teal: "\e[36m",
11
+ grey: "\x1b[38;5;248m",
12
+ reset: "\e[0m"
13
+ }
14
+ module Themes
15
+ DEFAULT = {
16
+ pass: :green,
17
+ fail: :red,
18
+ error: :yellow,
19
+ pending: :teal,
20
+ value: :magenta,
21
+ quiet: :grey
22
+ }
23
+ end
24
+
25
+ module Mixin
26
+ def with_color(status)
27
+ color = Conf[:colors][status] ||
28
+ raise("invalid status: #{status.inspect}")
29
+ code = ESC[color] || raise("invalid color #{color.inspect}")
30
+ # TODO: support color codes
31
+ print code if STDOUT.tty?
32
+ yield
33
+ print ESC[:reset] if STDOUT.tty?
34
+ end
35
+
36
+ def cprint(status, *strings)
37
+ with_color(status) { print(*strings) }
38
+ end
39
+
40
+ def cputs(status, *args)
41
+ with_color(status) { puts(*args) }
42
+ end
43
+ end
44
+
45
+ extend Mixin
46
+ end
47
+ end