easytest 0.8.1 → 0.9.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: 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