easytest 0.3.1 → 0.4.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 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