easytest 0.8.1 → 0.9.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: baf1f087a7353d74e8aa021313fd2f00c161af6cf5deb96552a5283e368f947f
4
- data.tar.gz: 9ccc8f17a4911d3bc77abdd3916e4344e2965047ffe7d47d6794d88e6d8dd754
3
+ metadata.gz: 9a953eabbcc6eb08f30507561d26309fd305983f9f6be7f0c2e2e1a1ce3410b5
4
+ data.tar.gz: 86ae0173c242a2069944836dcf48795960f29af50f3bb62c41aae2f079cc86df
5
5
  SHA512:
6
- metadata.gz: 7d907a3edc843501e6d20b408f358ca5cb0ec19b57a6ee7760577bbceff1fa078635209f439c0b5424ee72e2141c4a54ba51a8bb54c6a823406b55fd21246bd3
7
- data.tar.gz: 7c01539bb3762b24f27f5483e86837a05844b8495c6bb9450557d610e978a9011e8c9012c39bb8c7288d7fd6296b9257583298e8c2255cf74492d271b9b83012
6
+ metadata.gz: aeabfbd63843ff8edb06d2929f65c20c6a748da8f85f2d60b67dc87b7e446776cb76f524ae6ca48aae0601846a9f4da48b1d961f71f32b502697cff9a98e09e5
7
+ data.tar.gz: 87f634738fa05e63a1ac0e544965b15b72b6e66b44eccf806102894318f042eb286890cf1c559815c6681f958ec499e06fcbddae2fdee989c76430a7ff6460c2
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.9.0
6
+
7
+ - Add watch mode (`--watch`).
8
+ - Improve type coverage.
9
+
5
10
  ## 0.8.1
6
11
 
7
12
  - Improve type-checking.
data/README.md CHANGED
@@ -27,7 +27,7 @@ You can read more about Easytest on the [official website](https://ybiquitous.gi
27
27
 
28
28
  ## Usage
29
29
 
30
- Here is a very easy example.
30
+ This section explains easy usage.
31
31
 
32
32
  First, put `test/addition_test.rb` as below:
33
33
 
@@ -126,3 +126,13 @@ test "addition"
126
126
  ```
127
127
 
128
128
  To-do cases will be reported as "todo".
129
+
130
+ ### Watch
131
+
132
+ If you want to run tests immediately when changing code, specify the `--watch` option:
133
+
134
+ ```console
135
+ $ easytest --watch
136
+ ```
137
+
138
+ This *watch* mode is useful during development.
data/lib/easytest/case.rb CHANGED
@@ -9,7 +9,7 @@ module Easytest
9
9
  alias skipped? skipped
10
10
  alias only? only
11
11
 
12
- def initialize(name:, skipped: false, only: false, &block)
12
+ def initialize(name:, skipped: false, only: false, block: nil)
13
13
  @name = name
14
14
  @file = (caller_locations(3, 1)&.first&.absolute_path or raise)
15
15
  @block = block
data/lib/easytest/cli.rb CHANGED
@@ -8,9 +8,14 @@ module Easytest
8
8
  FATAL = 2
9
9
 
10
10
  def run
11
- exit_code = parse_options
11
+ exit_code = parse_argv
12
12
  return exit_code if exit_code
13
13
 
14
+ if watch?
15
+ watch_files
16
+ return SUCCESS
17
+ end
18
+
14
19
  Easytest.start
15
20
  setup
16
21
  successful = Easytest.run
@@ -21,33 +26,41 @@ module Easytest
21
26
 
22
27
  attr_reader :argv
23
28
  attr_reader :start_time
29
+ attr_reader :options
30
+ attr_reader :parser
24
31
 
25
32
  def initialize(argv)
26
33
  @argv = argv
27
34
  @start_time = Time.now
35
+ @options = {}
36
+ @parser = init_parser
28
37
  end
29
38
 
30
- def parse_options
31
- options = {}
39
+ def init_parser
40
+ OptionParser.new do |op|
41
+ op.program_name = "easytest"
42
+ op.version = "#{op.program_name} #{Easytest::VERSION}"
32
43
 
33
- parser = OptionParser.new do |p|
34
- p.program_name = "easytest"
35
- p.version = "#{p.program_name} #{Easytest::VERSION}"
44
+ op.on "-w", "--watch" do
45
+ options[:watch] = true
46
+ end
36
47
 
37
- p.on "--help" do
48
+ op.on "--help" do
38
49
  options[:help] = true
39
50
  end
40
51
 
41
- p.on "--version" do
52
+ op.on "--version" do
42
53
  options[:version] = true
43
54
  end
44
55
  end
56
+ end
45
57
 
58
+ def parse_argv
46
59
  begin
47
60
  parser.parse!(argv)
48
61
 
49
62
  if options[:help]
50
- puts help(parser)
63
+ puts help
51
64
  return SUCCESS
52
65
  end
53
66
 
@@ -63,37 +76,73 @@ module Easytest
63
76
  end
64
77
  end
65
78
 
66
- def help(parser)
79
+ def help
80
+ program = Rainbow(parser.program_name).green
81
+ heading = ->(text) { Rainbow(text).bright }
82
+ secondary = ->(text) { Rainbow(text).dimgray }
83
+ option = ->(text) { Rainbow(text).yellow }
84
+ prompt = ->() { Rainbow("$").cyan }
85
+
67
86
  <<~MSG
68
- #{Rainbow("USAGE").bright}
69
- #{parser.program_name} [options] [<file, directory, or pattern>...]
87
+ #{heading["USAGE"]}
88
+ #{program} [options] [<file, directory, or pattern>...]
70
89
 
71
- #{Rainbow("OPTIONS").bright}
72
- --help Show help
73
- --version Show version
90
+ #{heading["OPTIONS"]}
91
+ #{option["-w, --watch"]} Watch file changes and rerun test
92
+ #{option["--help"]} Show help
93
+ #{option["--version"]} Show version
74
94
 
75
- #{Rainbow("EXAMPLES").bright}
76
- # Run all tests (test/**/*_test.rb)
77
- $ easytest
95
+ #{heading["EXAMPLES"]}
96
+ #{secondary["# Run all tests (test/**/*_test.rb)"]}
97
+ #{prompt[]} #{program}
78
98
 
79
- # Run only test files
80
- $ easytest test/example_test.rb
99
+ #{secondary["# Run only test files"]}
100
+ #{prompt[]} #{program} test/example_test.rb
81
101
 
82
- # Run only test files in specified directories
83
- $ easytest test/example
102
+ #{secondary["# Run only test files in given directories"]}
103
+ #{prompt[]} #{program} test/example
84
104
 
85
- # Run only test files that matches specified patterns
86
- $ easytest example
105
+ #{secondary["# Run only test files that matches given patterns"]}
106
+ #{prompt[]} #{program} example
87
107
  MSG
88
108
  end
89
109
 
90
110
  def setup
91
- Dir.glob(Easytest.test_files_location)
92
- .map { |file| File.absolute_path(file) }
111
+ test_files
93
112
  .filter do |file|
94
113
  argv.empty? || argv.any? { |pattern| file.include?(pattern) }
95
114
  end
96
115
  .each { |test_file| load test_file }
97
116
  end
117
+
118
+ def test_files
119
+ Dir.glob(Easytest.test_files_location).map do |file|
120
+ File.absolute_path(file)
121
+ end
122
+ end
123
+
124
+ def watch?
125
+ options[:watch] == true
126
+ end
127
+
128
+ def watch_files
129
+ require "listen"
130
+ listener = Listen.to(Easytest.test_dir, only: /_test\.rb$/) do |modified, added|
131
+ Easytest.start(no_tests_forbidden: false)
132
+ test_files.intersection(modified + added).each do |file|
133
+ load(file)
134
+ end
135
+ Easytest.run
136
+ end
137
+ listener.start
138
+
139
+ begin
140
+ puts "Start watching \"#{Easytest.test_files_location}\" changed. Press Ctrl-C to stop."
141
+ sleep
142
+ rescue Interrupt
143
+ puts
144
+ puts "Stopped watching."
145
+ end
146
+ end
98
147
  end
99
148
  end
data/lib/easytest/dsl.rb CHANGED
@@ -3,25 +3,25 @@ module Easytest
3
3
  refine Kernel do
4
4
  def test(name, &block)
5
5
  Utils.raise_if_no_test_name(name, method: "test")
6
- Easytest.add_case Case.new(name: name, &block)
6
+ Easytest.add_case Case.new(name: name, block: block)
7
7
  end
8
8
 
9
9
  def before(&block)
10
- Easytest.add_hook Hook.new(type: :before, &block)
10
+ Easytest.add_hook Hook.new(type: :before, block: block)
11
11
  end
12
12
 
13
13
  def after(&block)
14
- Easytest.add_hook Hook.new(type: :after, &block)
14
+ Easytest.add_hook Hook.new(type: :after, block: block)
15
15
  end
16
16
 
17
17
  def skip(name, &block)
18
18
  Utils.raise_if_no_test_name(name, method: "skip")
19
- Easytest.add_case Case.new(name: name, skipped: true, &block)
19
+ Easytest.add_case Case.new(name: name, skipped: true, block: block)
20
20
  end
21
21
 
22
22
  def only(name, &block)
23
23
  Utils.raise_if_no_test_name(name, method: "only")
24
- Easytest.add_case Case.new(name: name, only: true, &block)
24
+ Easytest.add_case Case.new(name: name, only: true, block: block)
25
25
  end
26
26
 
27
27
  def expect(actual = nil, &block)
data/lib/easytest/hook.rb CHANGED
@@ -4,7 +4,7 @@ module Easytest
4
4
  attr_reader :type
5
5
  attr_reader :block
6
6
 
7
- def initialize(type:, &block)
7
+ def initialize(type:, block:)
8
8
  raise ArgumentError, "" unless [:before, :after].include?(type)
9
9
 
10
10
  @file = (caller_locations(3, 1)&.first&.absolute_path or raise)
@@ -2,7 +2,7 @@ module Easytest
2
2
  module Matcher
3
3
  class ContainExactly < Base
4
4
  def match?
5
- (actual.to_a - expected).empty?
5
+ (Array(actual) - Array(expected)).empty?
6
6
  end
7
7
 
8
8
  def message
@@ -1,21 +1,5 @@
1
1
  module Easytest
2
2
  class Runner
3
- attr_reader :start_time
4
- attr_accessor :passed_count
5
- attr_accessor :failed_count
6
- attr_accessor :skipped_count
7
- attr_accessor :todo_count
8
- attr_accessor :file_count
9
-
10
- def initialize(start_time: Time.now)
11
- @start_time = start_time
12
- @passed_count = 0
13
- @failed_count = 0
14
- @skipped_count = 0
15
- @todo_count = 0
16
- @file_count = 0
17
- end
18
-
19
3
  def run
20
4
  include_only_case = cases.any?(&:only?)
21
5
  hooks_by_file = hooks.group_by(&:file)
@@ -27,6 +11,7 @@ module Easytest
27
11
  before_hooks = hooks.filter(&:before?)
28
12
  after_hooks = hooks.filter(&:after?)
29
13
 
14
+ # @type var reports: Array[[Symbol, String]]
30
15
  reports = []
31
16
 
32
17
  cases_per_file.each do |c|
@@ -34,12 +19,13 @@ module Easytest
34
19
  c.skip!
35
20
  end
36
21
 
37
- begin
38
- before_hooks.each { |hook| hook.run(c) }
39
- result, report = c.run
40
- ensure
41
- after_hooks.each { |hook| hook.run(c) }
42
- end
22
+ result, report =
23
+ begin
24
+ before_hooks.each { |hook| hook.run(c) }
25
+ c.run
26
+ ensure
27
+ after_hooks.each { |hook| hook.run(c) }
28
+ end
43
29
 
44
30
  case result
45
31
  when :passed
@@ -69,12 +55,7 @@ module Easytest
69
55
  end
70
56
 
71
57
  if no_tests?
72
- $stderr.puts <<~MSG
73
- #{Rainbow("Oops. No tests found!").red.bright}
74
-
75
- #{Rainbow("Put `#{Easytest.test_files_location}` files to include at least one test case.").red}
76
- #{Rainbow("Or specify a pattern that matches an existing test file.").red}
77
- MSG
58
+ print_error_for_no_tests if no_tests_forbidden?
78
59
  false
79
60
  else
80
61
  puts ""
@@ -102,6 +83,26 @@ module Easytest
102
83
 
103
84
  private
104
85
 
86
+ attr_reader :start_time
87
+ attr_reader :no_tests_forbidden
88
+ alias no_tests_forbidden? no_tests_forbidden
89
+
90
+ attr_accessor :passed_count
91
+ attr_accessor :failed_count
92
+ attr_accessor :skipped_count
93
+ attr_accessor :todo_count
94
+ attr_accessor :file_count
95
+
96
+ def initialize(start_time: Time.now, no_tests_forbidden: true)
97
+ @start_time = start_time
98
+ @no_tests_forbidden = no_tests_forbidden
99
+ @passed_count = 0
100
+ @failed_count = 0
101
+ @skipped_count = 0
102
+ @todo_count = 0
103
+ @file_count = 0
104
+ end
105
+
105
106
  def total_count
106
107
  passed_count + failed_count + skipped_count + todo_count
107
108
  end
@@ -114,6 +115,15 @@ module Easytest
114
115
  total_count == 0
115
116
  end
116
117
 
118
+ def print_error_for_no_tests
119
+ $stderr.puts <<~MSG
120
+ #{Rainbow("Oops. No tests found!").red.bright}
121
+
122
+ #{Rainbow("Put `#{Easytest.test_files_location}` files to include at least one test case.").red}
123
+ #{Rainbow("Or specify a pattern that matches an existing test file.").red}
124
+ MSG
125
+ end
126
+
117
127
  def print_reports(reports)
118
128
  unexecuted = [:skipped, :todo]
119
129
  indent = " "
@@ -133,6 +143,7 @@ module Easytest
133
143
  end
134
144
 
135
145
  def summary
146
+ # @type var list: Array[String]
136
147
  list = []
137
148
 
138
149
  if failed_count > 0
@@ -1,3 +1,3 @@
1
1
  module Easytest
2
- VERSION = "0.8.1"
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/easytest.rb CHANGED
@@ -32,8 +32,8 @@ require_relative "easytest/matcher/satisfy"
32
32
  require_relative "easytest/matcher/true"
33
33
 
34
34
  module Easytest
35
- def self.start
36
- @runner = Runner.new
35
+ def self.start(no_tests_forbidden: true)
36
+ @runner = Runner.new(no_tests_forbidden: no_tests_forbidden)
37
37
  end
38
38
 
39
39
  def self.add_case(new_case)
@@ -48,7 +48,11 @@ module Easytest
48
48
  @runner.run
49
49
  end
50
50
 
51
+ def self.test_dir
52
+ "test"
53
+ end
54
+
51
55
  def self.test_files_location
52
- "test/**/*_test.rb"
56
+ "#{test_dir}/**/*_test.rb"
53
57
  end
54
58
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easytest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masafumi Koba
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-13 00:00:00.000000000 Z
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: listen
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.7'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rainbow
15
29
  requirement: !ruby/object:Gem::Requirement