rcheck 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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