m-spec 0.1.6 → 0.2.2
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 +4 -4
- data/.rubocop.yml +12 -0
- data/Gemfile +1 -1
- data/README.md +47 -4
- data/exe/m-spec +47 -2
- data/lib/m-spec.rb +2 -0
- data/lib/m-spec/core/helpers/readable.rb +9 -8
- data/lib/m-spec/core/matchers/output.rb +1 -1
- data/lib/m-spec/core/spec_example.rb +26 -0
- data/lib/m-spec/core/spec_result.rb +2 -2
- data/lib/m-spec/core/specs.rb +35 -0
- data/lib/m-spec/mocks/allow.rb +1 -1
- data/lib/m-spec/version.rb +1 -1
- data/m-spec.gemspec +2 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40b2437fce4d14eb4337f07a9d3f9ee43a9f6dc27591c19c4efadf53d05d83f3
|
4
|
+
data.tar.gz: 973c37628137445b7fbb1d0645bd657bfa6c6da14ee57426307f4bf0f0dfe3ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b69cdb674edf1cfc47ffb60c50d6fc6996f3ee49a60211f7941bc697f896514e9c3f62ef8fe77a346371fb2d1c61a830c0b8d792c9fd7bbb4716116efa09da7
|
7
|
+
data.tar.gz: c12a16300c6fcbb25ac84e5ade3d05ba57f2f830899b78ecbdc2e4ea62b62c80be6c99746130f116b15244a5575613b879444cb4050d21b1da8ca6e98583cebc
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# _____ ____ ____ __ _ __
|
2
|
+
# / ___/ _____ ____ _ / __// __/____ / / (_)____ / /_
|
3
|
+
# \__ \ / ___// __ `// /_ / /_ / __ \ / / / // __ \ / __/
|
4
|
+
# ___/ // /__ / /_/ // __// __// /_/ // /___ / // / / // /_
|
5
|
+
# /____/ \___/ \__,_//_/ /_/ 1 \____//_____//_//_/ /_/ \__/
|
6
|
+
#
|
7
|
+
# The linter file that doesn't lead junior developers to bad habits.
|
8
|
+
# https://github.com/makersacademy/scaffolint
|
9
|
+
#
|
10
|
+
# Configure Rubocop to use the config file in the Scaffolint GitHub repo
|
11
|
+
inherit_from:
|
12
|
+
- https://raw.githubusercontent.com/makersacademy/scaffolint/v1.1.0/.rubocop.yml
|
data/Gemfile
CHANGED
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
|
3
|
+
The lightest-weight spec framework in ruby. Built for learning at [Makers](https://makers.tech). You have two matchers, an equality matcher and an output matcher, and 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 '
|
47
|
-
it '
|
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,12 +94,28 @@ 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.
|
73
105
|
|
74
106
|
Remember - you'll have to manage yourself: test setup and teardown, keeping test code dry, each test running in isolation, and loading source code properly.
|
75
107
|
|
108
|
+
## Rubocop
|
109
|
+
|
110
|
+
M-spec comes with rubocop by default, using this [set of rules](https://github.com/makersacademy/scaffolint). To configure your test suite to disable rubocop or to only run rubcop, add an optional configuration file named `.m-spec` to your project root where you run your specs from. You don't need the configuration file - by default your specs will run first, followed by rubocop.
|
111
|
+
|
112
|
+
You can add either of two options
|
113
|
+
- `--no-rubocop` which will ignore running rubocop
|
114
|
+
- `--only-rubocop` which will ignore running your tests
|
115
|
+
|
116
|
+
See [rubocop documentation](https://docs.rubocop.org/rubocop/index.html) for more info - you might be interested in reading about rubocop's autocorrect command.
|
117
|
+
|
118
|
+
|
76
119
|
## Extending
|
77
120
|
|
78
121
|
After checking out the repo
|
data/exe/m-spec
CHANGED
@@ -1,5 +1,50 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'm-spec'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
def run_rubocop!
|
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
|
13
|
+
end
|
14
|
+
|
15
|
+
def run_specs!
|
16
|
+
spec_file = ARGV[0]
|
17
|
+
Mspec::Specs.new(spec_file).run!
|
18
|
+
end
|
19
|
+
|
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')
|
36
|
+
File.open('./.m-spec', 'r') do |file|
|
37
|
+
options = file.read.split
|
38
|
+
if options.include?('--only-rubocop')
|
39
|
+
run_rubocop!
|
40
|
+
elsif options.include?('--no-rubocop')
|
41
|
+
run_specs!
|
42
|
+
else
|
43
|
+
run_specs!
|
44
|
+
run_rubocop!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
run_specs!
|
49
|
+
run_rubocop!
|
50
|
+
end
|
data/lib/m-spec.rb
CHANGED
@@ -5,6 +5,8 @@ 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"
|
10
12
|
require "m-spec/core/helpers/readable"
|
@@ -9,21 +9,22 @@ def describe(str)
|
|
9
9
|
yield
|
10
10
|
end
|
11
11
|
|
12
|
-
def it(str)
|
13
|
-
|
14
|
-
|
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
|
-
|
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# #{
|
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)
|
@@ -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
|
|
@@ -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
|
data/lib/m-spec/mocks/allow.rb
CHANGED
data/lib/m-spec/version.rb
CHANGED
data/m-spec.gemspec
CHANGED
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
+
spec.add_dependency "rubocop", "~> 0.79.0"
|
26
|
+
|
25
27
|
spec.add_development_dependency "bundler", "~> 2.1"
|
26
28
|
spec.add_development_dependency "rake", ">= 12.3.3"
|
27
29
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: m-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
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-
|
11
|
+
date: 2020-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rubocop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.79.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.79.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -48,6 +62,7 @@ extensions: []
|
|
48
62
|
extra_rdoc_files: []
|
49
63
|
files:
|
50
64
|
- ".gitignore"
|
65
|
+
- ".rubocop.yml"
|
51
66
|
- CODE_OF_CONDUCT.md
|
52
67
|
- Gemfile
|
53
68
|
- LICENSE.txt
|
@@ -62,7 +77,9 @@ files:
|
|
62
77
|
- lib/m-spec/core/matchers/equal.rb
|
63
78
|
- lib/m-spec/core/matchers/output.rb
|
64
79
|
- lib/m-spec/core/spec_error.rb
|
80
|
+
- lib/m-spec/core/spec_example.rb
|
65
81
|
- lib/m-spec/core/spec_result.rb
|
82
|
+
- lib/m-spec/core/specs.rb
|
66
83
|
- lib/m-spec/mocks/allow.rb
|
67
84
|
- lib/m-spec/mocks/helpers/readable.rb
|
68
85
|
- lib/m-spec/mocks/mock.rb
|