easytest 0.3.1 → 0.4.0

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
  SHA256:
3
- metadata.gz: 720ee750084f63381ed7032f4c66bcd045e10b6fe96e9a3680bd5347d8ccdaf8
4
- data.tar.gz: 6b8b8c27ab380b898a2d52976ee3156e237041ff7d4f39006b9c3bd33c71b178
3
+ metadata.gz: e87217a9622ad5c57a2b97d64fc8e0a6cf32c264b53901644740b4727363d1bf
4
+ data.tar.gz: 5703988217fdf9bc1e0aad99c2c5609a6e159e80d546124f0108ba4414dc1638
5
5
  SHA512:
6
- metadata.gz: 7faecdb6f83e99f7ddf0216f03bcc1cd0407f14bd9417e84a4887db2d99c0ef7aaed94a33c513b0c487766d0ee7d28363a2e4c4f705774e7ce8fda5ad0406e67
7
- data.tar.gz: d33ea01dc76b139bba94125c4ca747cb07b2ac0c385bd96b27abbb1288e709ee2827d50bad957aad202c39eee2f21d16cb86f9b0b284b5ef804cdb145565ec38
6
+ metadata.gz: 98e353f726337a6d5b2b9aaad59a4bca8801f06885dc2e9f8f5c0dce6655e2d8e5ab178ede9f7d3b229e2e4f92b8896a5895454d211c8222570cf8e81ababea5
7
+ data.tar.gz: 88eff8410c841dffd3457beb20a3f78aaba46347ce724a680d9420f0e7831ce37d1ddcef9233a29758049a8b5e336f183781dc572b89531cd7472276984e5bb5
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.4.0
6
+
7
+ - Add `skip` and `test` without block for todo.
8
+ - Add `to_include` matcher.
9
+
5
10
  ## 0.3.1
6
11
 
7
12
  - Remove polyfill from `.sig` file.
data/README.md CHANGED
@@ -42,7 +42,7 @@ Then, run `easytest`:
42
42
  ```console
43
43
  $ easytest
44
44
  FAIL test/addition_test.rb
45
- addition (should equal)
45
+ addition (should equal)
46
46
 
47
47
  Expected: 2
48
48
  Received: 3
@@ -73,4 +73,21 @@ $ easytest
73
73
 
74
74
  The test now passes! 🎉
75
75
 
76
- For more, try `easytest --help`.
76
+ ### Skip
77
+
78
+ If you want to skip a case, you can change `test` to `skip`:
79
+
80
+ ```diff
81
+ -test "addition" do
82
+ +skip "addition" do
83
+ expect(1 + 2).to_eq 2
84
+ end
85
+ ```
86
+
87
+ ### To-do
88
+
89
+ If you want to write a to-do case, you can use `test` without a block:
90
+
91
+ ```ruby
92
+ test "addition"
93
+ ```
data/lib/easytest/case.rb CHANGED
@@ -3,35 +3,34 @@ module Easytest
3
3
  attr_reader :name
4
4
  attr_reader :file
5
5
  attr_reader :block
6
- attr_accessor :report
6
+ attr_reader :skipped
7
+ alias skipped? skipped
7
8
 
8
- def initialize(name:, file:, &block)
9
+ def initialize(name:, file:, skipped: false, &block)
9
10
  @name = name
10
11
  @file = file
11
12
  @block = block
12
- @report = nil
13
+ @skipped = skipped
13
14
  end
14
15
 
15
- def run
16
- block.call
17
- true
18
- rescue MatchError, FatalError => error
19
- loc = find_location(error) or raise
20
-
21
- self.report = Reporter.new(
22
- name: name,
23
- error: error,
24
- file: loc.absolute_path,
25
- location: loc.to_s,
26
- ).report or raise
27
-
28
- false
16
+ def todo?
17
+ block.nil?
29
18
  end
30
19
 
31
- private
20
+ def run
21
+ if todo?
22
+ return [:todo, Reporter.new(name).report_todo]
23
+ end
24
+
25
+ if skipped?
26
+ return [:skipped, Reporter.new(name).report_skip]
27
+ end
32
28
 
33
- def find_location(error)
34
- error.backtrace_locations.find { |loc| loc.path.end_with?("_test.rb") }
29
+ block.call
30
+ [:passed, nil]
31
+ rescue MatchError, FatalError => error
32
+ report = Reporter.new(name).report_error(error) or raise error
33
+ [:failed, report]
35
34
  end
36
35
  end
37
36
  end
data/lib/easytest/cli.rb CHANGED
@@ -66,7 +66,7 @@ module Easytest
66
66
  def help(parser)
67
67
  <<~MSG
68
68
  #{Rainbow("USAGE").bright}
69
- #{parser.program_name} [options] [...<file, directory, or pattern>]
69
+ #{parser.program_name} [options] [<file, directory, or pattern>...]
70
70
 
71
71
  #{Rainbow("OPTIONS").bright}
72
72
  --help Show help
data/lib/easytest/dsl.rb CHANGED
@@ -2,10 +2,19 @@ module Easytest
2
2
  module DSL
3
3
  refine Kernel do
4
4
  def test(name, &block)
5
+ raise FatalError, "`test` requires a name" if name.nil? || name.empty?
6
+
5
7
  file = caller_locations(1, 1).first.absolute_path
6
8
  Easytest.add_case Case.new(name: name, file: file, &block)
7
9
  end
8
10
 
11
+ def skip(name, &block)
12
+ raise FatalError, "`skip` requires a name" if name.nil? || name.empty?
13
+
14
+ file = caller_locations(1, 1).first.absolute_path
15
+ Easytest.add_case Case.new(name: name, file: file, skipped: true, &block)
16
+ end
17
+
9
18
  def expect(actual = nil, &block)
10
19
  Expectation.new(actual, &block)
11
20
  end
@@ -37,6 +37,10 @@ module Easytest
37
37
  Matcher::InstanceOf.new(actual: actual, expected: expected, negate: negate).match!
38
38
  end
39
39
 
40
+ def to_include(expected)
41
+ Matcher::Include.new(actual: actual, expected: expected, negate: negate).match!
42
+ end
43
+
40
44
  def to_raise(expected)
41
45
  raise FatalError, "`to_raise` requires a block like `expect { ... }.to_raise`" unless block
42
46
  raise FatalError, "`not.to_raise` can cause a false positive, so use `to_not_raise` instead" if negate?
@@ -0,0 +1,13 @@
1
+ module Easytest
2
+ module Matcher
3
+ class Include < Base
4
+ def match?
5
+ actual.include? expected
6
+ end
7
+
8
+ def message
9
+ "include"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,47 +1,65 @@
1
1
  module Easytest
2
2
  class Reporter
3
3
  attr_reader :name
4
- attr_reader :error
5
- attr_reader :file
6
- attr_reader :location
7
4
 
8
- def initialize(name:, error:, file:, location:)
5
+ def initialize(name)
9
6
  @name = name
10
- @error = error
11
- @file = file
12
- @location = location
13
7
  end
14
8
 
15
- def report
9
+ def report_error(error)
16
10
  case error
17
11
  when MatchError
18
- report_match_error
12
+ report_match_error(error)
19
13
  when FatalError
20
- report_fatal_error
14
+ report_fatal_error(error)
21
15
  end
22
16
  end
23
17
 
18
+ def report_skip
19
+ Rainbow("⚠ skipped \"#{name}\"").yellow
20
+ end
21
+
22
+ def report_todo
23
+ Rainbow("✎ todo \"#{name}\"").magenta
24
+ end
25
+
24
26
  private
25
27
 
26
- def report_match_error
28
+ def report_match_error(error)
29
+ loc = find_location(error)
30
+
27
31
  <<~MSG
28
- #{Rainbow(" #{name}").red.bright} #{Rainbow("(#{error.message})").dimgray}
32
+ #{Rainbow(" #{name}").red.bright} #{Rainbow("(#{error.message})").dimgray}
29
33
 
30
34
  #{Rainbow("Expected: #{error.expected.inspect}").green}
31
35
  #{Rainbow("Received: #{error.actual.inspect}").red}
32
36
 
33
- #{Rainbow("# #{location}").dimgray}
37
+ #{Rainbow(format_location(loc)).dimgray}
34
38
  MSG
35
39
  end
36
40
 
37
- def report_fatal_error
41
+ def report_fatal_error(error)
42
+ loc = find_location(error)
43
+
38
44
  <<~MSG
39
- #{Rainbow(" #{name}").red.bright}
45
+ #{Rainbow(" #{name}").red.bright}
40
46
 
41
47
  #{Rainbow(error.message).red}
42
48
 
43
- #{Rainbow("# #{location}").dimgray}
49
+ #{Rainbow(format_location(loc)).dimgray}
44
50
  MSG
45
51
  end
52
+
53
+ def find_location(error)
54
+ location = error.backtrace_locations.find do |loc|
55
+ loc.path.end_with?("_test.rb")
56
+ end
57
+ location or raise "Not found test location from #{error.inspect}"
58
+ end
59
+
60
+ def format_location(location)
61
+ path = Pathname(location.absolute_path).relative_path_from(Dir.pwd)
62
+ "# #{path}:#{location.lineno}:in `#{location.label}'"
63
+ end
46
64
  end
47
65
  end
@@ -3,12 +3,16 @@ module Easytest
3
3
  attr_reader :start_time
4
4
  attr_accessor :passed_count
5
5
  attr_accessor :failed_count
6
+ attr_accessor :skipped_count
7
+ attr_accessor :todo_count
6
8
  attr_accessor :file_count
7
9
 
8
10
  def initialize(start_time: Time.now)
9
11
  @start_time = start_time
10
12
  @passed_count = 0
11
13
  @failed_count = 0
14
+ @skipped_count = 0
15
+ @todo_count = 0
12
16
  @file_count = 0
13
17
  end
14
18
 
@@ -16,26 +20,49 @@ module Easytest
16
20
  cases_by_file = cases.group_by { |c| c.file }
17
21
  cases_by_file.each do |file, cases|
18
22
  self.file_count += 1
23
+
19
24
  reports = []
20
25
 
21
26
  cases.each do |c|
22
- passed = c.run
27
+ result, report = c.run
23
28
 
24
- if passed
29
+ case result
30
+ when :passed
25
31
  self.passed_count += 1
26
- else
32
+ when :failed
27
33
  self.failed_count += 1
28
- reports << c.report.gsub(/^/, " ")
34
+ when :skipped
35
+ self.skipped_count += 1
36
+ when :todo
37
+ self.todo_count += 1
38
+ else
39
+ raise "Unknown result: #{result.inspect}"
29
40
  end
41
+
42
+ reports << [result, report] if report
30
43
  end
31
44
 
32
45
  link = Utils.terminal_hyperlink(file)
33
- if reports.empty?
46
+
47
+ if reports.none? { |result, _| result == :failed }
34
48
  puts "#{Rainbow(" PASS ").bright.bg(:green)} #{link}"
35
49
  else
36
50
  puts "#{Rainbow(" FAIL ").bright.bg(:red)} #{link}"
37
- reports.each { |report| puts report ; puts "" }
38
51
  end
52
+
53
+ reports
54
+ .sort_by do |result, _|
55
+ case result
56
+ when :skipped, :todo
57
+ 0
58
+ else
59
+ 1
60
+ end
61
+ end
62
+ .each do |result, report|
63
+ puts report.gsub(/^/, " ").gsub(/^\s+$/, "")
64
+ puts "" if result == :failed
65
+ end
39
66
  end
40
67
 
41
68
  if no_tests?
@@ -65,7 +92,7 @@ module Easytest
65
92
  private
66
93
 
67
94
  def total_count
68
- passed_count + failed_count
95
+ passed_count + failed_count + skipped_count + todo_count
69
96
  end
70
97
 
71
98
  def all_passed?
@@ -81,16 +108,24 @@ module Easytest
81
108
  end
82
109
 
83
110
  def summary
84
- summary = ""
111
+ list = []
85
112
 
86
- if failed_count == 0
87
- summary << Rainbow("#{passed_count} passed").green.bright
88
- else
89
- summary << Rainbow("#{failed_count} failed").red.bright
90
- summary << ", #{Rainbow("#{passed_count} passed").green.bright}"
113
+ if failed_count > 0
114
+ list << Rainbow("#{failed_count} failed").red.bright
115
+ end
116
+
117
+ if skipped_count > 0
118
+ list << Rainbow("#{skipped_count} skipped").yellow.bright
91
119
  end
92
120
 
93
- summary << ", #{total_count} total #{Rainbow("(#{file_count} files)").dimgray}"
121
+ if todo_count > 0
122
+ list << Rainbow("#{todo_count} todo").magenta.bright
123
+ end
124
+
125
+ list << Rainbow("#{passed_count} passed").green.bright
126
+ list << "#{total_count} total #{Rainbow("(#{file_count} files)").dimgray}"
127
+
128
+ list.join(", ")
94
129
  end
95
130
  end
96
131
  end
@@ -1,3 +1,3 @@
1
1
  module Easytest
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/easytest.rb CHANGED
@@ -17,6 +17,7 @@ require_relative "easytest/matcher/be"
17
17
  require_relative "easytest/matcher/be_a"
18
18
  require_relative "easytest/matcher/equal"
19
19
  require_relative "easytest/matcher/false"
20
+ require_relative "easytest/matcher/include"
20
21
  require_relative "easytest/matcher/instance_of"
21
22
  require_relative "easytest/matcher/kind_of"
22
23
  require_relative "easytest/matcher/nil"
data/sig/easytest.rbs CHANGED
@@ -21,12 +21,19 @@ module Easytest
21
21
  def to_be_false: () -> void
22
22
  def to_be_true: () -> void
23
23
 
24
+ def to_include: (untyped expected) -> void
25
+
24
26
  def to_raise: ((Class | String | Regexp) expected) -> void
25
27
  def to_not_raise: () -> void
26
28
  end
27
29
  end
28
30
 
29
31
  module Kernel
32
+ # TODO: Can we avoid `RBS::DuplicatedMethodDefinitionError` "::Kernel#test has duplicated definitions"?
33
+ # def test: (String name) ?{ () -> void } -> void
34
+
35
+ def skip: (String name) { () -> void } -> void
36
+
30
37
  def expect: (untyped actual) -> Easytest::Expectation
31
38
  | { () -> void } -> Easytest::Expectation
32
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easytest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masafumi Koba
@@ -47,6 +47,7 @@ files:
47
47
  - lib/easytest/matcher/be_a.rb
48
48
  - lib/easytest/matcher/equal.rb
49
49
  - lib/easytest/matcher/false.rb
50
+ - lib/easytest/matcher/include.rb
50
51
  - lib/easytest/matcher/instance_of.rb
51
52
  - lib/easytest/matcher/kind_of.rb
52
53
  - lib/easytest/matcher/nil.rb