petitest 0.1.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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +105 -0
  7. data/Rakefile +6 -0
  8. data/lib/petitest/assertion_failure_error.rb +4 -0
  9. data/lib/petitest/assertion_failure_message.rb +35 -0
  10. data/lib/petitest/assertions.rb +46 -0
  11. data/lib/petitest/autorun.rb +8 -0
  12. data/lib/petitest/configuration.rb +26 -0
  13. data/lib/petitest/subscribers/base_subscriber.rb +21 -0
  14. data/lib/petitest/subscribers/json_report_subscriber.rb +38 -0
  15. data/lib/petitest/subscribers/progress_report_subscriber.rb +23 -0
  16. data/lib/petitest/subscribers/timer_subscriber.rb +26 -0
  17. data/lib/petitest/test_case.rb +125 -0
  18. data/lib/petitest/test_cases_runner.rb +58 -0
  19. data/lib/petitest/test_group.rb +51 -0
  20. data/lib/petitest/test_method.rb +25 -0
  21. data/lib/petitest/texts/base_text.rb +54 -0
  22. data/lib/petitest/texts/error_message_text.rb +20 -0
  23. data/lib/petitest/texts/errors_element_text.rb +54 -0
  24. data/lib/petitest/texts/errors_text.rb +45 -0
  25. data/lib/petitest/texts/failure_message_text.rb +20 -0
  26. data/lib/petitest/texts/failures_element_text.rb +54 -0
  27. data/lib/petitest/texts/failures_text.rb +45 -0
  28. data/lib/petitest/texts/filtered_backtrace_text.rb +20 -0
  29. data/lib/petitest/texts/raised_code_text.rb +48 -0
  30. data/lib/petitest/texts/test_case_result_character_text.rb +29 -0
  31. data/lib/petitest/texts/test_cases_result_margin_top_text.rb +24 -0
  32. data/lib/petitest/texts/test_cases_result_text.rb +45 -0
  33. data/lib/petitest/texts/test_counts_text.rb +96 -0
  34. data/lib/petitest/texts/times_text.rb +47 -0
  35. data/lib/petitest/version.rb +3 -0
  36. data/lib/petitest.rb +36 -0
  37. data/petitest.gemspec +24 -0
  38. metadata +108 -0
@@ -0,0 +1,54 @@
1
+ module Petitest
2
+ module Texts
3
+ class BaseText
4
+ ANSI_COLOR_CODE_BY_COLOR_TYPE = {
5
+ black: 30,
6
+ blue: 34,
7
+ bold: 1,
8
+ cyan: 36,
9
+ green: 32,
10
+ magenta: 35,
11
+ red: 31,
12
+ white: 37,
13
+ yellow: 33,
14
+ }
15
+
16
+ # @note Override
17
+ def to_s
18
+ raise ::NotImplementedError
19
+ end
20
+
21
+ private
22
+
23
+ # @param color_type [Symbol]
24
+ # @return [Integer]
25
+ def ansi_color_code_for(color_type)
26
+ ANSI_COLOR_CODE_BY_COLOR_TYPE[configured_color_name_for(color_type)] || ANSI_COLOR_CODE_BY_COLOR_TYPE[:white]
27
+ end
28
+
29
+ # @param color_type [Symbol]
30
+ # @return [Symbol, nil]
31
+ def configured_color_name_for(color_type)
32
+ ::Petitest.configuration.color_scheme[color_type]
33
+ end
34
+
35
+ # @param string [String]
36
+ # @param color_type [Symbol]
37
+ # @return [String]
38
+ def colorize(string, color_type)
39
+ if ::Petitest.configuration.colored
40
+ "\e[#{ansi_color_code_for(color_type)}m#{string}\e[0m"
41
+ else
42
+ string
43
+ end
44
+ end
45
+
46
+ # @param string [String]
47
+ # @param level [Integer]
48
+ # @return [String]
49
+ def indent(string, level)
50
+ string.gsub(/^(?!$)/, " " * level)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,20 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class ErrorMessageText < ::Petitest::Texts::BaseText
6
+ # @return [Petitest::TestCase]
7
+ attr_reader :test_case
8
+
9
+ # @param test_case [Petitest::TestCase]
10
+ def initialize(test_case:)
11
+ @test_case = test_case
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ colorize("#{test_case.error_class_name}: #{test_case.error_message}", :error)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class ErrorsElementText < ::Petitest::Texts::BaseText
6
+ # @return [Integer]
7
+ attr_reader :index
8
+
9
+ # @return [Petitest::TestCase]
10
+ attr_reader :test_case
11
+
12
+ # @param index [Integer]
13
+ # @param test_case [Petitest::TestCase]
14
+ def initialize(index:, test_case:)
15
+ @index = index
16
+ @test_case = test_case
17
+ end
18
+
19
+ # @note Override
20
+ def to_s
21
+ [
22
+ heading,
23
+ indent(body, 2)
24
+ ].join("\n")
25
+ end
26
+
27
+ private
28
+
29
+ # @return [String]
30
+ def body
31
+ [
32
+ ::Petitest::Texts::RaisedCodeText.new(test_case: test_case),
33
+ ::Petitest::Texts::ErrorMessageText.new(test_case: test_case),
34
+ ::Petitest::Texts::FilteredBacktraceText.new(test_case: test_case),
35
+ ].join("\n")
36
+ end
37
+
38
+ # @return [String]
39
+ def heading
40
+ "#{ordinal_number}) #{test_signature}"
41
+ end
42
+
43
+ # @return [Integer]
44
+ def ordinal_number
45
+ index + 1
46
+ end
47
+
48
+ # @return [String]
49
+ def test_signature
50
+ test_case.test_signature
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class ErrorsText < ::Petitest::Texts::BaseText
6
+ # @return [Array<Petitest::TestCase>]
7
+ attr_reader :test_cases
8
+
9
+ # @param test_cases [Array<Petitest::TestCase>]
10
+ def initialize(test_cases:)
11
+ @test_cases = test_cases
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ [
17
+ heading,
18
+ indent(body, 2),
19
+ ].join("\n\n")
20
+ end
21
+
22
+ private
23
+
24
+ # @return [String]
25
+ def body
26
+ errors_element_texts.join("\n\n")
27
+ end
28
+
29
+ # @return [Array<Petitest::Textx::FailuresElementText>]
30
+ def errors_element_texts
31
+ test_cases.map.with_index do |test_case, index|
32
+ ::Petitest::Texts::ErrorsElementText.new(
33
+ index: index,
34
+ test_case: test_case,
35
+ )
36
+ end
37
+ end
38
+
39
+ # @return [String]
40
+ def heading
41
+ "Errors:"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class FailureMessageText < ::Petitest::Texts::BaseText
6
+ # @return [Petitest::TestCase]
7
+ attr_reader :test_case
8
+
9
+ # @param test_case [Petitest::TestCase]
10
+ def initialize(test_case:)
11
+ @test_case = test_case
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ colorize(test_case.failure_message, :failure)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class FailuresElementText < ::Petitest::Texts::BaseText
6
+ # @return [Integer]
7
+ attr_reader :index
8
+
9
+ # @return [Petitest::TestCase]
10
+ attr_reader :test_case
11
+
12
+ # @param index [Integer]
13
+ # @param test_case [Petitest::TestCase]
14
+ def initialize(index:, test_case:)
15
+ @index = index
16
+ @test_case = test_case
17
+ end
18
+
19
+ # @note Override
20
+ def to_s
21
+ [
22
+ heading,
23
+ indent(body, 2)
24
+ ].join("\n")
25
+ end
26
+
27
+ private
28
+
29
+ # @return [String]
30
+ def body
31
+ [
32
+ ::Petitest::Texts::RaisedCodeText.new(test_case: test_case),
33
+ ::Petitest::Texts::FailureMessageText.new(test_case: test_case),
34
+ ::Petitest::Texts::FilteredBacktraceText.new(test_case: test_case),
35
+ ].join("\n")
36
+ end
37
+
38
+ # @return [String]
39
+ def heading
40
+ "#{ordinal_number}) #{test_signature}"
41
+ end
42
+
43
+ # @return [Integer]
44
+ def ordinal_number
45
+ index + 1
46
+ end
47
+
48
+ # @return [String]
49
+ def test_signature
50
+ test_case.test_signature
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class FailuresText < ::Petitest::Texts::BaseText
6
+ # @return [Array<Petitest::TestCase>]
7
+ attr_reader :test_cases
8
+
9
+ # @param test_cases [Array<Petitest::TestCase>]
10
+ def initialize(test_cases:)
11
+ @test_cases = test_cases
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ [
17
+ heading,
18
+ indent(body, 2),
19
+ ].join("\n\n")
20
+ end
21
+
22
+ private
23
+
24
+ # @return [String]
25
+ def body
26
+ failures_element_texts.join("\n\n")
27
+ end
28
+
29
+ # @return [Array<Petitest::Textx::FailuresElementText>]
30
+ def failures_element_texts
31
+ test_cases.map.with_index do |test_case, index|
32
+ ::Petitest::Texts::FailuresElementText.new(
33
+ index: index,
34
+ test_case: test_case,
35
+ )
36
+ end
37
+ end
38
+
39
+ # @return [String]
40
+ def heading
41
+ "Failures:"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class FilteredBacktraceText < ::Petitest::Texts::BaseText
6
+ # @return [Petitest::TestCase]
7
+ attr_reader :test_case
8
+
9
+ # @param test_case [Petitest::TestCase]
10
+ def initialize(test_case:)
11
+ @test_case = test_case
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ colorize(test_case.filtered_backtrace.join("\n").gsub(/^/, "# "), :detail)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,48 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class RaisedCodeText < ::Petitest::Texts::BaseText
6
+ # @return [Petitest::TestCase]
7
+ attr_reader :test_case
8
+
9
+ # @param test_case [Petitest::TestCase]
10
+ def initialize(test_case:)
11
+ @test_case = test_case
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ if content = caller_file_content
17
+ content.lines[caller_line_number - 1].strip
18
+ else
19
+ ""
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # @return [String, nil]
26
+ def caller_file_content
27
+ if ::FileTest.file?(caller_path)
28
+ ::File.read(caller_path)
29
+ end
30
+ end
31
+
32
+ # @return [String]
33
+ def caller_line_number
34
+ caller_segments[1].to_i
35
+ end
36
+
37
+ # @return [String]
38
+ def caller_path
39
+ caller_segments[0]
40
+ end
41
+
42
+ # @return [Array<String>]
43
+ def caller_segments
44
+ @caller_segments ||= test_case.filtered_backtrace[0].split(":", 3)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class TestCaseResultCharacterText < ::Petitest::Texts::BaseText
6
+ # @return [Petitest::TestCase]
7
+ attr_reader :test_case
8
+
9
+ # @param test_case [Petitest::TestCase]
10
+ def initialize(test_case:)
11
+ @test_case = test_case
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ case
17
+ when test_case.aborted?
18
+ colorize("E", :error)
19
+ when test_case.failed?
20
+ colorize("F", :failure)
21
+ when test_case.skipped?
22
+ colorize("*", :skip)
23
+ else
24
+ "."
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class TestCasesResultMarginTopText < ::Petitest::Texts::BaseText
6
+ # @return [Array<Petitest::TestCase>]
7
+ attr_reader :test_cases
8
+
9
+ # @param test_cases [Array<Petitest::TestCase>]
10
+ def initialize(test_cases:)
11
+ @test_cases = test_cases
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ if test_cases.empty?
17
+ "\n"
18
+ else
19
+ "\n\n"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class TestCasesResultText < ::Petitest::Texts::BaseText
6
+ # @return [Time]
7
+ attr_reader :finished_at
8
+
9
+ # @return [Time]
10
+ attr_reader :started_at
11
+
12
+ # @return [Array<Petitest::TestCase>]
13
+ attr_reader :test_cases
14
+
15
+ # @param finished_at [Time]
16
+ # @param started_at [Time]
17
+ # @param test_cases [Array<Petitest::TestCase>]
18
+ def initialize(
19
+ finished_at:,
20
+ started_at:,
21
+ test_cases:
22
+ )
23
+ @finished_at = finished_at
24
+ @started_at = started_at
25
+ @test_cases = test_cases
26
+ end
27
+
28
+ # @note Override
29
+ def to_s
30
+ [
31
+ ::Petitest::Texts::TestCasesResultMarginTopText.new(test_cases: test_cases),
32
+ [
33
+ ::Petitest::Texts::FailuresText.new(test_cases: test_cases.select(&:failed?)),
34
+ ::Petitest::Texts::ErrorsText.new(test_cases: test_cases.select(&:aborted?)),
35
+ ::Petitest::Texts::TestCountsText.new(test_cases: test_cases),
36
+ ::Petitest::Texts::TimesText.new(
37
+ finished_at: finished_at,
38
+ started_at: started_at,
39
+ ),
40
+ ].join("\n\n"),
41
+ ].join
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,96 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class TestCountsText < ::Petitest::Texts::BaseText
6
+ # @return [Array<Petitest::TestCase>]
7
+ attr_reader :test_cases
8
+
9
+ # @param test_cases [Array<Petitest::TestCase>]
10
+ def initialize(test_cases:)
11
+ @test_cases = test_cases
12
+ end
13
+
14
+ # @note Override
15
+ def to_s
16
+ [
17
+ heading,
18
+ indent(body, 2),
19
+ ].join("\n\n")
20
+ end
21
+
22
+ private
23
+
24
+ # @return [String]
25
+ def body
26
+ [
27
+ text_of_count_of_test_cases,
28
+ text_of_count_of_passed_test_cases,
29
+ text_of_count_of_failed_test_cases,
30
+ text_of_count_of_aborted_test_cases,
31
+ text_of_count_of_skipped_test_cases,
32
+ ].join("\n")
33
+ end
34
+
35
+ # @return [Integer]
36
+ def count_of_aborted_test_cases
37
+ test_cases.select(&:aborted?).length
38
+ end
39
+
40
+ # @return [Integer]
41
+ def count_of_failed_test_cases
42
+ test_cases.select(&:failed?).length
43
+ end
44
+
45
+ # @return [Integer]
46
+ def count_of_passed_test_cases
47
+ test_cases.select(&:passed?).length
48
+ end
49
+
50
+ # @return [Integer]
51
+ def count_of_skipped_test_cases
52
+ test_cases.select(&:skipped?).length
53
+ end
54
+
55
+ # @return [Integer]
56
+ def count_of_test_cases
57
+ test_cases.length
58
+ end
59
+
60
+ # @return [String]
61
+ def heading
62
+ "Counts:"
63
+ end
64
+
65
+ # @return [Integer]
66
+ def max_digits_length
67
+ @max_digits_length ||= count_of_test_cases.to_s.length
68
+ end
69
+
70
+ # @return [String]
71
+ def text_of_count_of_aborted_test_cases
72
+ colorize("%#{max_digits_length}d errors" % count_of_aborted_test_cases, :error)
73
+ end
74
+
75
+ # @return [String]
76
+ def text_of_count_of_failed_test_cases
77
+ colorize("%#{max_digits_length}d failures" % count_of_failed_test_cases, :failure)
78
+ end
79
+
80
+ # @return [String]
81
+ def text_of_count_of_passed_test_cases
82
+ colorize("%#{max_digits_length}d passes" % count_of_passed_test_cases, :pass)
83
+ end
84
+
85
+ # @return [String]
86
+ def text_of_count_of_skipped_test_cases
87
+ colorize("%#{max_digits_length}d skips" % count_of_skipped_test_cases, :skip)
88
+ end
89
+
90
+ # @return [String]
91
+ def text_of_count_of_test_cases
92
+ "%#{max_digits_length}d tests" % count_of_test_cases
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,47 @@
1
+ require "petitest/texts/base_text"
2
+
3
+ module Petitest
4
+ module Texts
5
+ class TimesText < ::Petitest::Texts::BaseText
6
+ # @return [Time]
7
+ attr_reader :finished_at
8
+
9
+ # @return [Time]
10
+ attr_reader :started_at
11
+
12
+ # @param finished_at [Time]
13
+ # @param started_at [Time]
14
+ def initialize(
15
+ finished_at:,
16
+ started_at:
17
+ )
18
+ @finished_at = finished_at
19
+ @started_at = started_at
20
+ end
21
+
22
+ # @note Override
23
+ def to_s
24
+ [
25
+ heading,
26
+ indent(body, 2),
27
+ ].join("\n\n")
28
+ end
29
+
30
+ private
31
+
32
+ # @return [String]
33
+ def body
34
+ [
35
+ "Started: #{started_at.iso8601(6)}",
36
+ "Finished: #{finished_at.iso8601(6)}",
37
+ "Total: %.6fs" % (finished_at - started_at),
38
+ ].join("\n")
39
+ end
40
+
41
+ # @return [String]
42
+ def heading
43
+ "Times:"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Petitest
2
+ VERSION = "0.1.0"
3
+ end
data/lib/petitest.rb ADDED
@@ -0,0 +1,36 @@
1
+ require "petitest/assertion_failure_error"
2
+ require "petitest/assertion_failure_message"
3
+ require "petitest/assertions"
4
+ require "petitest/configuration"
5
+ require "petitest/subscribers/base_subscriber"
6
+ require "petitest/subscribers/json_report_subscriber"
7
+ require "petitest/subscribers/progress_report_subscriber"
8
+ require "petitest/subscribers/timer_subscriber"
9
+ require "petitest/test_case"
10
+ require "petitest/test_cases_runner"
11
+ require "petitest/test_group"
12
+ require "petitest/test_method"
13
+ require "petitest/texts/base_text"
14
+ require "petitest/texts/error_message_text"
15
+ require "petitest/texts/errors_element_text"
16
+ require "petitest/texts/errors_text"
17
+ require "petitest/texts/failure_message_text"
18
+ require "petitest/texts/failures_element_text"
19
+ require "petitest/texts/failures_text"
20
+ require "petitest/texts/filtered_backtrace_text"
21
+ require "petitest/texts/raised_code_text"
22
+ require "petitest/texts/test_case_result_character_text"
23
+ require "petitest/texts/test_cases_result_margin_top_text"
24
+ require "petitest/texts/test_cases_result_text"
25
+ require "petitest/texts/test_counts_text"
26
+ require "petitest/texts/times_text"
27
+ require "petitest/version"
28
+
29
+ module Petitest
30
+ class << self
31
+ # @return [Petitest::Configuration]
32
+ def configuration
33
+ @configuration ||= ::Petitest::Configuration.new
34
+ end
35
+ end
36
+ end
data/petitest.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "petitest/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "petitest"
7
+ spec.version = Petitest::VERSION
8
+ spec.authors = ["Ryo Nakamura"]
9
+ spec.email = ["r7kamura@gmail.com"]
10
+ spec.summary = "A minimal solid testing framework for Ruby."
11
+ spec.homepage = "https://github.com/r7kamura/petitest"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
15
+ f.match(%r{^(test|spec|features)/})
16
+ end
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = ">= 2.1.0"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.14"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end