m-spec 0.1.4 → 0.2.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: 857fb56c14bef8568ca65cfb7b8dd8a690276d39db4a074ff4ff1bcc87f40623
4
- data.tar.gz: e1e45c135ad1ba9fa443ce1bedd7c29da423801487132e486685ef348539cef2
3
+ metadata.gz: f055e58c3c0edff2cede566c4eb387246d69b4ee536773ad95addb2b52e6074b
4
+ data.tar.gz: 58c017bc787dbeefc2411e4131b0681ca1be035ec1bc1d0c9b08765d1e010588
5
5
  SHA512:
6
- metadata.gz: 58a02ecbc7553aefa81164debb276264ab9e434a76c5702d4b1081283ed0f4e7523d7d92c7742b27b49a0a0692282a2dea9eb15c6caf5d3b338063735c1f0d34
7
- data.tar.gz: 41d3a4c22032f454c9b4176307457020fda0a2ee00ff7564a736dd1d9b035a3f72203f8940910e4dd32af2e270aeda564636fff7ced719b7b075a8c50c2733dc
6
+ metadata.gz: 2a4861aebb496805aa16426fa16c6d1fb0fd1f555aa2118946eb03ee5227eece185f0e528eb4433cd9ce81d64bd3c61ccfc0e1bb581d253b9fb6a1b1a5ceba03
7
+ data.tar.gz: '082a188d2374df2fb7af946b27e346828b26990166edd2dfbf655ed300dd1d2910559adcaff0f6cb71dc350e8ce7d11bc6c2e85b60dca9f6e8d04ad5b106bd21'
@@ -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/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 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
 
@@ -43,19 +43,32 @@ describe 'The Animal' do
43
43
  end
44
44
  end
45
45
 
46
- describe 'stubbing' do
47
- it 'we can mock too!' do
46
+ describe 'test doubles' do
47
+ it 'can be stubbed' do
48
48
  mock = test_double
49
49
  allow(mock).to receive(:speak) { 'Hello!' }
50
50
  expect(mock.speak).to eq 'Hello!'
51
51
  end
52
+ it 'can have optional names' do
53
+ mock = test_double('a name')
54
+ allow(mock).to receive(:speak) { 'Hello!' }
55
+ expect(mock.speak).to eq 'Hello!'
56
+ end
57
+ end
58
+
59
+ describe 'testing output' do
60
+ it 'captures strings' do
61
+ expect { puts('hello') }.to output("hello\n")
62
+ end
52
63
  end
53
64
  ```
54
65
 
55
- To run your specs, pass the spec file directly as an argument. You have to run individual spec files.
66
+ 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
67
 
57
68
  ```sh
58
69
  $ m-spec ./spec/animal_spec.rb
70
+ # or
71
+ $ m-spec ./spec_runner.rb
59
72
  ```
60
73
 
61
74
  ```
@@ -64,14 +77,30 @@ The Animal
64
77
  fails nicely
65
78
  Expected: ROAAAARRRR!
66
79
  Got: little roar!
67
- /path/to/directory/spec/animal_spec.rb:11:in `block (2 levels) in <top (required)>'
80
+ # /path/to/directory/spec/animal_spec.rb:11:in `block (2 levels) in <top (required)>'
68
81
  stubbing
69
82
  we can mock too!
83
+
84
+ Inspecting 3 files
85
+ ...
86
+
87
+ 3 files inspected, no offenses detected
70
88
  ```
71
89
 
72
90
  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
91
 
74
- Remember - you'll have to manage test setup and teardown yourself and keeping your test code dry yourself. Make sure each test runs in isolation.
92
+ 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.
93
+
94
+ ## Rubocop
95
+
96
+ 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.
97
+
98
+ You can add either of two options
99
+ - `--no-rubocop` which will ignore running rubocop
100
+ - `--only-rubocop` which will ignore running your tests
101
+
102
+ See [rubocop documentation](https://docs.rubocop.org/rubocop/index.html) for more info - you might be interested in reading about rubocop's autocorrect command.
103
+
75
104
 
76
105
  ## Extending
77
106
 
@@ -88,7 +117,7 @@ m-spec [spec-file]
88
117
  ```
89
118
 
90
119
  ## Pushing to Rubygems
91
- Sign up for an account, check for the gem name you want, and then follow the hints and errors when you
120
+ Sign up for an account, check for the gem name you want, change the gem metadata to represent what you want, and then follow the hints and errors when you
92
121
  ```sh
93
122
  $ bundle exec rake release
94
123
  ```
data/exe/m-spec CHANGED
@@ -1,5 +1,46 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'm-spec'
3
3
 
4
- spec_file = ARGV[0]
5
- require spec_file
4
+ def run_rubocop!
5
+ # needs default
6
+ if File.exists?('.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 root or re-initialize m-spec with `m-spec --init`"
11
+ end
12
+ end
13
+
14
+ def run_specs!
15
+ spec_file = ARGV[0]
16
+ Mspec::Specs.new(spec_file).run!
17
+ end
18
+
19
+ if ARGV[0] == '--init'
20
+ contents = File.read("#{ENV['GEM_HOME']}/gems/m-spec-#{Mspec::VERSION}/.rubocop.yml")
21
+ File.open('.rubocop.yml', 'w') do |file|
22
+ file.write(contents)
23
+ end
24
+ puts 'created: .rubocop.yml'
25
+
26
+ contents = "# This has been auto-generated. Feel free to delete these comments.\n#\n# Try adding options below: '--no-rubocop' or '--only-rubocop' without the quotes."
27
+ File.open('.m-spec', 'w') do |file|
28
+ file.write(contents)
29
+ end
30
+ puts 'created: .m-spec'
31
+ elsif File.exists?('./.m-spec')
32
+ File.open('./.m-spec', 'r') do |file|
33
+ options = file.read.split
34
+ if options.include?('--only-rubocop')
35
+ run_rubocop!
36
+ elsif options.include?('--no-rubocop')
37
+ run_specs!
38
+ else
39
+ run_specs!
40
+ run_rubocop!
41
+ end
42
+ end
43
+ else
44
+ run_specs!
45
+ run_rubocop!
46
+ end
@@ -1,9 +1,14 @@
1
+ require 'stringio'
2
+
1
3
  require "m-spec/version"
2
4
 
3
5
  require "m-spec/core/expect"
4
6
  require "m-spec/core/spec_error"
5
7
  require "m-spec/core/spec_result"
8
+ require "m-spec/core/spec_example"
9
+ require "m-spec/core/specs"
6
10
  require "m-spec/core/matchers/equal"
11
+ require "m-spec/core/matchers/output"
7
12
  require "m-spec/core/helpers/readable"
8
13
 
9
14
  require "m-spec/mocks/allow"
@@ -9,21 +9,31 @@ 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
+
16
+ if spec_example.success?
15
17
  puts " \e[#{COLOUR_CODES[:green]}m#{str}\e[0m"
16
18
  else
17
19
  puts " \e[#{COLOUR_CODES[:red]}m#{str}\e[0m"
18
- spec_result.failure_message.each do |line|
20
+ spec_example.failure_message.each do |line|
19
21
  puts " \e[#{COLOUR_CODES[:red]}m#{line}\e[0m"
20
22
  end
21
- puts " \e[#{COLOUR_CODES[:light_blue]}m# #{spec_result.trace}\e[0m"
23
+ puts " \e[#{COLOUR_CODES[:light_blue]}m# #{spec_example.trace}\e[0m"
24
+ end
25
+ end
26
+
27
+ def expect(obj=nil, &block)
28
+ if !obj.nil?
29
+ Mspec::Expect.new(obj)
30
+ else
31
+ Mspec::Expect.new(block)
22
32
  end
23
33
  end
24
34
 
25
- def expect(obj)
26
- Mspec::Expect.new(obj)
35
+ def output(string)
36
+ Mspec::Matchers::Output.new(string)
27
37
  end
28
38
 
29
39
  def eq(obj)
@@ -0,0 +1,31 @@
1
+ require 'stringio'
2
+
3
+ module Mspec
4
+ module Matchers
5
+ class Output
6
+ attr_reader :value, :test_code_output_string
7
+
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def check(block)
13
+ output = mock_output do
14
+ block.call
15
+ end
16
+ @test_code_output_string = output.string
17
+
18
+ @value == @test_code_output_string
19
+ end
20
+
21
+ private
22
+
23
+ def mock_output(output=StringIO.new, &block)
24
+ $stdout = output
25
+ block.call
26
+ $stdout = STDOUT
27
+ output
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
@@ -1,8 +1,8 @@
1
1
  module Mspec
2
2
  class SpecResult
3
3
  def initialize(expectation, matcher, error)
4
- @expectation = expectation
5
- @matcher = matcher
4
+ @test_code = expectation
5
+ @expected_result = matcher
6
6
  @error = error
7
7
  end
8
8
 
@@ -12,13 +12,23 @@ module Mspec
12
12
 
13
13
  def failure_message
14
14
  [
15
- "Expected: #{@expectation.value}",
16
- "Got: #{@matcher.value}",
15
+ "Expected: ".rjust(9) + "#{@expected_result.value.inspect}",
16
+ "Got: ".rjust(9) + "#{test_code_result.inspect}",
17
17
  ]
18
18
  end
19
19
 
20
20
  def trace
21
21
  "#{@error.backtrace[1]}"
22
22
  end
23
+
24
+ private
25
+
26
+ def test_code_result
27
+ if @test_code.value.is_a?(Proc)
28
+ @expected_result.test_code_output_string
29
+ else
30
+ @test_code.value
31
+ end
32
+ end
23
33
  end
24
34
  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
@@ -1,3 +1,3 @@
1
1
  module Mspec
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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.1.4
4
+ version: 0.2.0
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-06-25 00:00:00.000000000 Z
11
+ date: 2020-08-13 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
@@ -60,8 +75,11 @@ files:
60
75
  - lib/m-spec/core/expect.rb
61
76
  - lib/m-spec/core/helpers/readable.rb
62
77
  - lib/m-spec/core/matchers/equal.rb
78
+ - lib/m-spec/core/matchers/output.rb
63
79
  - lib/m-spec/core/spec_error.rb
80
+ - lib/m-spec/core/spec_example.rb
64
81
  - lib/m-spec/core/spec_result.rb
82
+ - lib/m-spec/core/specs.rb
65
83
  - lib/m-spec/mocks/allow.rb
66
84
  - lib/m-spec/mocks/helpers/readable.rb
67
85
  - lib/m-spec/mocks/mock.rb