rspec-log_matcher 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5cff49aaad12c7e78ee918b21bba1e19d609b5098d0da6dfad8d58a91f64dd23
4
+ data.tar.gz: d19d360da5c337292ca0e85a15de74a080cc4ecc1469118fad5a96c7a64f44e2
5
+ SHA512:
6
+ metadata.gz: a284eb8e2aa71e6a6f69b0b7fbd3c5f68cabab1a5713845b456641070d42c022039d8bbfcc14819d3167e15e27b8d1d548ee7a089df7244143110762aa226367
7
+ data.tar.gz: '08cde836ee3666ea3f5133e535ca27f263fee6de0906681e8838e6a1b7c49d5c2892ea54fbe626a023bd31698ff9c23e7a5cba8a8035651651b6d815a67130d2'
@@ -0,0 +1,7 @@
1
+ # master
2
+
3
+ # 1.0.0
4
+
5
+ * Log matcher added
6
+
7
+ *Juan Manuel Ramallo*
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Juan Manuel Ramallo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,114 @@
1
+ # RSpec::LogMatcher
2
+
3
+ ## What is this?
4
+ An RSpec custom matcher to test code that logs information into log files.
5
+
6
+ Writing logs is an easy way to store any kind of information for further analysis later on. It's commonly used to store analytics events and then make the logs a data source for data engineering tasks. This matcher makes application-logging-testing easier.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ group :test do
14
+ gem 'rspec-log_matcher'
15
+ end
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle install
21
+
22
+ ## Usage
23
+
24
+ ### Plain old ruby objects
25
+
26
+ ```ruby
27
+ # app/services/payment_service.rb
28
+ class PaymentService
29
+ def self.call
30
+ # [snip]
31
+
32
+ logger.info "event=payment-successful properties=#{data.to_json}"
33
+ end
34
+ end
35
+ ```
36
+
37
+ ```ruby
38
+ # spec/services/payment_service_spec.rb
39
+ require 'spec_helper'
40
+
41
+ RSpec.describe PaymentService
42
+ describe '.call' do
43
+ subject { described_class.call }
44
+
45
+ it 'logs event information' do
46
+ expect { subject }.to log("event=payment-successful properties=#{build_expected_json}")
47
+ end
48
+ end
49
+ end
50
+ ```
51
+
52
+ ### Request specs
53
+ ```ruby
54
+ # spec/requests/users_spec.rb
55
+ require 'spec_helper'
56
+
57
+ RSpec.describe 'Users' do
58
+ describe 'GET /index' do
59
+ expect { get(users_path) }.to log('Page view - Users index')
60
+ end
61
+ end
62
+ ```
63
+
64
+ ### Feature specs
65
+
66
+ ```ruby
67
+ # spec/features/sign_in_spec.rb
68
+ require 'spec_helper'
69
+
70
+ RSpec.feature 'Sign in' do
71
+ scenario 'successful sign in' do
72
+ user = create(:user)
73
+
74
+ visit sign_in_path
75
+ fill_form(user)
76
+ submit_form
77
+
78
+ expect(page).to have_text('Welcome!')
79
+ expect(page).to log("User #{user.id} has logged in")
80
+ end
81
+ end
82
+ ```
83
+
84
+ Regular expressions and procs are also valid object types for the expected logs, for more use cases refer to the [spec file](https://github.com/juanmanuelramallo/rspec-log_matcher/blob/master/spec/rspec-log_matcher_spec.rb).
85
+
86
+ ## Configuration
87
+
88
+ The default path for the log file is `log/test.log`. It can be configured via an environment variable called `LOG_PATH`.
89
+
90
+ This is useful when tests are run parallely, and each process has their own log file.
91
+
92
+ ## How it works?
93
+
94
+ The matcher reads into the log file and looks for the expected logs to be present in the log file.
95
+
96
+ When the subject is a proc, the matcher will execute proc and compare against the logs introduced by the proc execution.
97
+
98
+ When the subject is a Capybara::Session (from a feature spec, system tests), the matcher will store the position in the file to the last byte in a before hook. Then, when the example is run, it will compare against the changes introduced by the example using the position stored as the beginning of the logs.
99
+
100
+ ## Development
101
+
102
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
103
+
104
+ ## Contributing
105
+
106
+ Bug reports and pull requests are welcome on GitHub at https://github.com/juanmanuelramallo/rspec-log_matcher. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/juanmanuelramallo/rspec-log_matcher/blob/master/CODE_OF_CONDUCT.md).
107
+
108
+ ## License
109
+
110
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
111
+
112
+ ## Code of Conduct
113
+
114
+ Everyone interacting in the Rspec::LogMatcher project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/juanmanuelramallo/rspec-log_matcher/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/log_matcher'
4
+
5
+ module RSpec
6
+ module LogMatcher
7
+ class Error < StandardError; end
8
+
9
+ def log(expected_logs)
10
+ Matcher.new(expected_logs, @log_file_position)
11
+ end
12
+
13
+ ::RSpec.configure do |config|
14
+ config.before(:each, type: :feature) do
15
+ @log_file_position = File.new(Matcher::LOG_PATH).sysseek(0, IO::SEEK_END)
16
+ end
17
+
18
+ config.include ::RSpec::LogMatcher
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/log_matcher/version'
4
+ require 'rspec/log_matcher/matcher'
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module LogMatcher
5
+ class Matcher
6
+ LOG_PATH = ENV.fetch('LOG_PATH', 'log/test.log')
7
+
8
+ attr_reader :expected_logs, :initial_log_file_position
9
+
10
+ def initialize(expected_logs, initial_log_file_position)
11
+ @expected_logs = expected_logs
12
+ @initial_log_file_position = initial_log_file_position || 0
13
+ end
14
+
15
+ def matches?(subject)
16
+ prepare_matcher(subject)
17
+
18
+ case expected_logs
19
+ when Regexp
20
+ logs.match?(expected_logs)
21
+ when Proc
22
+ logs.include?(expected_logs.call)
23
+ when String
24
+ logs.include?(expected_logs)
25
+ end
26
+ end
27
+
28
+ def failure_message
29
+ "Expected subject to have logged `#{expected_logs}' in:\n\t#{logs}"
30
+ end
31
+
32
+ def failure_message_when_negated
33
+ "Expected subject not to have logged `#{expected_logs}' in:\n\t#{logs}"
34
+ end
35
+
36
+ def supports_block_expectations?
37
+ true
38
+ end
39
+
40
+ private
41
+
42
+ def log_file
43
+ @log_file ||= File.new(LOG_PATH)
44
+ end
45
+
46
+ def logs
47
+ @logs ||= log_file.read
48
+ end
49
+
50
+ def prepare_matcher(subject)
51
+ if subject.is_a?(Proc)
52
+ log_file.seek(0, IO::SEEK_END)
53
+ subject.call
54
+ elsif defined?(Capybara::Session) && subject.is_a?(Capybara::Session)
55
+ log_file.seek(initial_log_file_position)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module LogMatcher
5
+ MAJOR = 1
6
+ MINOR = 0
7
+ PATCH = 0
8
+
9
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-log_matcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Juan Manuel Ramallo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '4'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '4'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 3.9.0
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 3.9.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rubocop
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.91'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.91'
61
+ - !ruby/object:Gem::Dependency
62
+ name: simplecov
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.17.1
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.17.1
75
+ description: Writing logs is an easy way to store any kind of information for further
76
+ analysis later on. It's commonly used to store analytics events and then make the
77
+ logs a source for data engineering tasks. This matcher makes logging testing easier.
78
+ email:
79
+ - juanmanuelramallo@hey.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - CHANGELOG.md
85
+ - LICENSE.txt
86
+ - README.md
87
+ - lib/rspec-log_matcher.rb
88
+ - lib/rspec/log_matcher.rb
89
+ - lib/rspec/log_matcher/matcher.rb
90
+ - lib/rspec/log_matcher/version.rb
91
+ homepage: https://github.com/juanmanuelramallo/rspec-log_matcher
92
+ licenses:
93
+ - MIT
94
+ metadata:
95
+ homepage_uri: https://github.com/juanmanuelramallo/rspec-log_matcher
96
+ source_code_uri: https://github.com/juanmanuelramallo/rspec-log_matcher
97
+ changelog_uri: https://github.com/juanmanuelramallo/rspec-log_matcher/blob/master/CHANGELOG.md
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 2.3.0
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubygems_version: 3.1.2
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: RSpec custom matcher to test code that logs information into log files.
117
+ test_files: []