m-spec 0.1.7 → 0.2.3

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: 1dcf77e4015cb8bb7c3a1e9c0bdba696607e9b5e1c194498cb260373e7038921
4
- data.tar.gz: 81821b568580532c5b5c4cf18b457f947185a83932d4b9359b57b3e85c211502
3
+ metadata.gz: 4f6acd7d54cf75d89e1c6775a87596f48765d537726dbde5bfb9f7edbf94d8b3
4
+ data.tar.gz: dc0fc6487f6b34ebb5bed6fad56c1eaf9b8fb7a834d302deeafd95095fa5433a
5
5
  SHA512:
6
- metadata.gz: 4638a25c2f039e6bbb4a550db34a1b228414e30037209b50ea273e7173717eed1e931f5bc58bffd888041e0f6a84b54d46fc770bcd970f8ca98c9a150f7af72b
7
- data.tar.gz: f1ede96eae952c17fb581b02741cadf44ea619bb0dade5a69f0b27133f482a1642cf8c3e22fee17c2ff8fac7cc7b4aa3172e8b3d0060d6ab3e036d3eefd9012f
6
+ metadata.gz: 709cbf7e8ac930b83c63c575dbac520bdf49d56eaf9c479f917504f1400e0f2f382426cab4639c3ceae3a17b1aa99dee31151aceffdaa441ee3f457ad96a0a1a
7
+ data.tar.gz: d64e4dd9cad0bcd54a0c988fa733d53de9a94df8030605d79c01a03632c29bad3ae5977394b736a403dd5ecd727c6fbb0faa01509b249d552013c63e5dd3184b
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in mspec.gemspec
6
6
  gemspec
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mspec
2
2
 
3
- The lightest-weight spec framework in ruby. Built for learning at [Makers](https://makers.tech). You have one matcher, the comparison matcher, and test setup and teardown is your responsibility. For additional features, you must extend the gem.
3
+ The lightest-weight spec framework in ruby. Built for learning at [Makers](https://makers.tech). You have three matchers, an equality matcher, an output matcher and an error matcher. Test setup and teardown is your responsibility. For additional features, you must extend the gem.
4
4
 
5
5
  ## Installation
6
6
 
@@ -18,6 +18,14 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install m-spec
20
20
 
21
+ ## Setup
22
+
23
+ Initialize m-spec with a `.m-spec` and a `.rubocop.yml` file
24
+ ```sh
25
+ m-spec --init
26
+ ```
27
+
28
+
21
29
  ## Usage
22
30
 
23
31
  We care about isolating unit tests, so there's a very simple mocking library.
@@ -43,19 +51,38 @@ describe 'The Animal' do
43
51
  end
44
52
  end
45
53
 
46
- describe 'stubbing' do
47
- it 'we can mock too!' do
54
+ describe 'test doubles' do
55
+ it 'can be stubbed' do
48
56
  mock = test_double
49
57
  allow(mock).to receive(:speak) { 'Hello!' }
50
58
  expect(mock.speak).to eq 'Hello!'
51
59
  end
60
+ it 'can have optional names' do
61
+ mock = test_double('a name')
62
+ allow(mock).to receive(:speak) { 'Hello!' }
63
+ expect(mock.speak).to eq 'Hello!'
64
+ end
65
+
66
+ it 'can be sent messages with any args' do
67
+ mock = test_double('a name')
68
+ allow(mock).to receive(:speak) { 'Hello!' }
69
+ expect(mock.speak('example arg')).to eq 'Hello!'
70
+ end
71
+ end
72
+
73
+ describe 'testing output' do
74
+ it 'captures strings' do
75
+ expect { puts('hello') }.to output("hello\n")
76
+ end
52
77
  end
53
78
  ```
54
79
 
55
- To run your specs, pass the spec file directly as an argument. You have to run individual spec files.
80
+ To run your specs, pass the spec file directly as an argument. You have to run individual spec files, or create a file that requires your specs.
56
81
 
57
82
  ```sh
58
83
  $ m-spec ./spec/animal_spec.rb
84
+ # or
85
+ $ m-spec ./spec_runner.rb
59
86
  ```
60
87
 
61
88
  ```
@@ -67,6 +94,11 @@ The Animal
67
94
  # /path/to/directory/spec/animal_spec.rb:11:in `block (2 levels) in <top (required)>'
68
95
  stubbing
69
96
  we can mock too!
97
+
98
+ Inspecting 3 files
99
+ ...
100
+
101
+ 3 files inspected, no offenses detected
70
102
  ```
71
103
 
72
104
  It's got simple one-level indentation, simple colour coding for test passes and failures, and simple failure messages with expected and actual values and the failing spec file path and line number.
data/exe/m-spec CHANGED
@@ -2,16 +2,37 @@
2
2
  require 'm-spec'
3
3
 
4
4
  def run_rubocop!
5
- config = "$GEM_HOME/gems/m-spec-#{Mspec::VERSION}/.rubocop.yml"
6
- system("bundle exec rubocop --config #{config}")
5
+ # needs default
6
+ if File.exist?('.rubocop.yml')
7
+ puts "\n---Readability Tests---\n\n"
8
+ system("bundle exec rubocop")
9
+ else
10
+ puts "ERROR: No '.rubocop.yml' found, please create one at your project \
11
+ root or re-initialize m-spec with `m-spec --init`"
12
+ end
7
13
  end
8
14
 
9
15
  def run_specs!
10
16
  spec_file = ARGV[0]
11
- require spec_file
17
+ Mspec::Specs.new(spec_file).run!
12
18
  end
13
19
 
14
- if File.exists?('./.m-spec')
20
+ if ARGV[0] == '--init'
21
+ contents = File.read("#{ENV['GEM_HOME']}/gems/m-spec-#{Mspec::VERSION}/.rubocop.yml")
22
+ File.open('.rubocop.yml', 'w') do |file|
23
+ file.write(contents)
24
+ end
25
+ puts 'created: .rubocop.yml'
26
+
27
+ contents =
28
+ "# This has been auto-generated. Feel free to delete these comments.\
29
+ \n#\n# Try adding options below: '--no-rubocop' or '--only-rubocop' \
30
+ without the quotes."
31
+ File.open('.m-spec', 'w') do |file|
32
+ file.write(contents)
33
+ end
34
+ puts 'created: .m-spec'
35
+ elsif File.exist?('./.m-spec')
15
36
  File.open('./.m-spec', 'r') do |file|
16
37
  options = file.read.split
17
38
  if options.include?('--only-rubocop')
@@ -5,8 +5,12 @@ require "m-spec/version"
5
5
  require "m-spec/core/expect"
6
6
  require "m-spec/core/spec_error"
7
7
  require "m-spec/core/spec_result"
8
+ require "m-spec/core/spec_example"
9
+ require "m-spec/core/specs"
8
10
  require "m-spec/core/matchers/equal"
9
11
  require "m-spec/core/matchers/output"
12
+ require "m-spec/core/matchers/raise_error"
13
+
10
14
  require "m-spec/core/helpers/readable"
11
15
 
12
16
  require "m-spec/mocks/allow"
@@ -9,21 +9,22 @@ def describe(str)
9
9
  yield
10
10
  end
11
11
 
12
- def it(str)
13
- spec_result = yield
14
- if spec_result.success?
12
+ def it(str, specs = Mspec::Specs.instance)
13
+ spec_example = Mspec::SpecExample.new(str, yield)
14
+ specs.add(spec_example)
15
+ if spec_example.success?
15
16
  puts " \e[#{COLOUR_CODES[:green]}m#{str}\e[0m"
16
17
  else
17
- puts " \e[#{COLOUR_CODES[:red]}m#{str}\e[0m"
18
- spec_result.failure_message.each do |line|
18
+ puts " \e[#{COLOUR_CODES[:red]}m#{str}\n\e[0m"
19
+ spec_example.failure_message.each do |line|
19
20
  puts " \e[#{COLOUR_CODES[:red]}m#{line}\e[0m"
20
21
  end
21
- puts " \e[#{COLOUR_CODES[:light_blue]}m# #{spec_result.trace}\e[0m"
22
+ puts "\n \e[#{COLOUR_CODES[:light_blue]}m# #{spec_example.trace}\e[0m"
22
23
  end
23
24
  end
24
25
 
25
- def expect(obj=nil, &block)
26
- if obj
26
+ def expect(obj = nil, &block)
27
+ if !obj.nil?
27
28
  Mspec::Expect.new(obj)
28
29
  else
29
30
  Mspec::Expect.new(block)
@@ -37,3 +38,7 @@ end
37
38
  def eq(obj)
38
39
  Mspec::Matchers::Equal.new(obj)
39
40
  end
41
+
42
+ def raise_error(error_class)
43
+ Mspec::Matchers::RaiseError.new(error_class)
44
+ end
@@ -3,7 +3,7 @@ require 'stringio'
3
3
  module Mspec
4
4
  module Matchers
5
5
  class Output
6
- attr_reader :value, :test_code_output_string
6
+ attr_reader :value, :actual
7
7
 
8
8
  def initialize(value)
9
9
  @value = value
@@ -13,14 +13,14 @@ module Mspec
13
13
  output = mock_output do
14
14
  block.call
15
15
  end
16
- @test_code_output_string = output.string
16
+ @actual = output.string
17
17
 
18
- @value == @test_code_output_string
18
+ @value == @actual
19
19
  end
20
20
 
21
21
  private
22
22
 
23
- def mock_output(output=StringIO.new, &block)
23
+ def mock_output(output = StringIO.new, &block)
24
24
  $stdout = output
25
25
  block.call
26
26
  $stdout = STDOUT
@@ -0,0 +1,31 @@
1
+ require 'stringio'
2
+
3
+ module Mspec
4
+ module Matchers
5
+ class RaiseError
6
+ attr_reader :value, :actual
7
+
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def check(block)
13
+ @actual = catch_error do
14
+ block.call
15
+ end
16
+
17
+ @value == @actual
18
+ end
19
+
20
+ private
21
+
22
+ def catch_error(&block)
23
+ begin
24
+ block.call
25
+ rescue StandardError => e
26
+ e.class
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module Mspec
2
+ class SpecExample
3
+ attr_reader :description, :result
4
+
5
+ def initialize(description, result)
6
+ @description = description
7
+ @result = result
8
+ end
9
+
10
+ def success?
11
+ @result.success?
12
+ end
13
+
14
+ def failure?
15
+ !success?
16
+ end
17
+
18
+ def failure_message
19
+ @result.failure_message
20
+ end
21
+
22
+ def trace
23
+ @result.trace
24
+ end
25
+ end
26
+ end
@@ -12,8 +12,8 @@ module Mspec
12
12
 
13
13
  def failure_message
14
14
  [
15
- "Expected: #{@expected_result.value.inspect}",
16
- "Got: #{test_code_result.inspect}",
15
+ "Expected: ".rjust(10) + "#{@expected_result.value.inspect}",
16
+ "Got: ".rjust(10) + "#{test_code_result.inspect}",
17
17
  ]
18
18
  end
19
19
 
@@ -25,7 +25,7 @@ module Mspec
25
25
 
26
26
  def test_code_result
27
27
  if @test_code.value.is_a?(Proc)
28
- @expected_result.test_code_output_string
28
+ @expected_result.actual
29
29
  else
30
30
  @test_code.value
31
31
  end
@@ -0,0 +1,35 @@
1
+ module Mspec
2
+ class Specs
3
+ attr_reader :data
4
+
5
+ def initialize(file)
6
+ @file = file
7
+ @data = []
8
+ @@instance = self
9
+ end
10
+
11
+ def run!
12
+ require(@file)
13
+ summary
14
+ end
15
+
16
+ def add(spec)
17
+ @data << spec
18
+ end
19
+
20
+ def self.instance
21
+ @@instance
22
+ end
23
+
24
+ def summary
25
+ puts "\n---Summary---\n\n"
26
+ puts "#{@data.length} examples found"
27
+ failures = @data.select(&:failure?)
28
+
29
+ puts "#{failures.length} failures"
30
+ failures.each_with_index do |spec, index|
31
+ puts " \e[#{COLOUR_CODES[:red]}m#{index+1}. #{spec.trace}\e[0m"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -6,7 +6,7 @@ module Mspec
6
6
  end
7
7
 
8
8
  def to(stub)
9
- @obj.define_singleton_method(stub.name) { stub.return_value }
9
+ @obj.define_singleton_method(stub.name) { |*| stub.return_value }
10
10
  end
11
11
  end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module Mspec
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: m-spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edward Withers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-05 00:00:00.000000000 Z
11
+ date: 2020-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -76,8 +76,11 @@ files:
76
76
  - lib/m-spec/core/helpers/readable.rb
77
77
  - lib/m-spec/core/matchers/equal.rb
78
78
  - lib/m-spec/core/matchers/output.rb
79
+ - lib/m-spec/core/matchers/raise_error.rb
79
80
  - lib/m-spec/core/spec_error.rb
81
+ - lib/m-spec/core/spec_example.rb
80
82
  - lib/m-spec/core/spec_result.rb
83
+ - lib/m-spec/core/specs.rb
81
84
  - lib/m-spec/mocks/allow.rb
82
85
  - lib/m-spec/mocks/helpers/readable.rb
83
86
  - lib/m-spec/mocks/mock.rb