skunk 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.reek.yml +8 -8
- data/.rubocop_todo.yml +19 -5
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +77 -0
- data/Gemfile.lock +8 -8
- data/LICENSE.txt +22 -0
- data/README.md +72 -6
- data/bin/console +2 -0
- data/lib/skunk/cli/application.rb +0 -1
- data/lib/skunk/cli/command_factory.rb +1 -1
- data/lib/skunk/cli/commands/compare.rb +44 -0
- data/lib/skunk/cli/commands/default.rb +2 -5
- data/lib/skunk/cli/commands/status_reporter.rb +17 -10
- data/lib/skunk/rubycritic/analysed_module.rb +1 -1
- data/lib/skunk/rubycritic/analysed_modules_collection.rb +17 -0
- data/lib/skunk/version.rb +1 -1
- data/samples/rubycritic/analysed_module.rb +47 -0
- data/skunk.gemspec +2 -2
- metadata +14 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df70466af9db8ae3849245db231b15bcee039470542d750b54dc27d6cc27f11f
|
4
|
+
data.tar.gz: eed948e603c3f94226ed2eb4ede37397f731675401d34d70731069113af233c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93b44bae842a25cca17a1708bbe2b7ba1a1b4fea072130d9609967fad908f16c0d54b16df3eb8c21e4cf222414a925bb671c9b06782b9aa3576c2893d96db1ee
|
7
|
+
data.tar.gz: f7ef68ea2c9b5513183aec2757380e6b62b53def85be94d9e144562d47d9352e30703f81e99f18db7b8b2d8ceb526a5cffb896054f60f049171388d9333dbaa6
|
data/.reek.yml
CHANGED
@@ -4,22 +4,22 @@ detectors:
|
|
4
4
|
UtilityFunction:
|
5
5
|
exclude:
|
6
6
|
- capture_output_streams
|
7
|
+
- Skunk::Command::Compare#analyse_modified_files
|
8
|
+
- Skunk::Command::Compare#build_details_path
|
7
9
|
InstanceVariableAssumption:
|
8
10
|
exclude:
|
9
11
|
- Skunk::Cli::Application
|
10
12
|
- Skunk::Cli::Command::Default
|
11
|
-
|
12
|
-
exclude:
|
13
|
-
- Skunk::Cli::Application
|
14
|
-
- Skunk::Cli::Command::Default
|
15
|
-
- Skunk::Cli::Command::Help
|
16
|
-
- Skunk::Command::StatusReporter
|
17
|
-
- Skunk::Cli::Options
|
18
|
-
- RubyCritic::AnalysedModule
|
13
|
+
- RubyCritic::AnalysedModulesCollection
|
19
14
|
TooManyStatements:
|
20
15
|
exclude:
|
21
16
|
- initialize
|
22
17
|
- Skunk::Cli::Application#execute
|
18
|
+
IrresponsibleModule:
|
19
|
+
exclude:
|
20
|
+
- Skunk::Cli::Command::Help
|
21
|
+
- Skunk::Cli::Options
|
22
|
+
- RubyCritic::AnalysedModulesCollection
|
23
23
|
Attribute:
|
24
24
|
exclude:
|
25
25
|
- Skunk::Command::StatusReporter#analysed_modules
|
data/.rubocop_todo.yml
CHANGED
@@ -1,16 +1,30 @@
|
|
1
1
|
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config
|
3
|
-
# on 2019-
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2019-11-09 15:45:44 -0500 using RuboCop version 0.75.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
9
|
# Offense count: 1
|
10
|
+
# Cop supports --auto-correct.
|
11
|
+
Layout/ClosingHeredocIndentation:
|
12
|
+
Exclude:
|
13
|
+
- 'lib/skunk/cli/commands/status_reporter.rb'
|
14
|
+
|
15
|
+
# Offense count: 1
|
16
|
+
# Cop supports --auto-correct.
|
17
|
+
# Configuration parameters: EnforcedStyle.
|
18
|
+
# SupportedStyles: squiggly, active_support, powerpack, unindent
|
19
|
+
Layout/IndentHeredoc:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/skunk/cli/commands/status_reporter.rb'
|
22
|
+
|
23
|
+
# Offense count: 2
|
10
24
|
# Configuration parameters: CountComments, ExcludedMethods.
|
11
25
|
# ExcludedMethods: refine
|
12
26
|
Metrics/BlockLength:
|
13
|
-
Max:
|
27
|
+
Max: 40
|
14
28
|
|
15
29
|
# Offense count: 1
|
16
30
|
# Cop supports --auto-correct.
|
@@ -19,9 +33,9 @@ Naming/RescuedExceptionsVariableName:
|
|
19
33
|
Exclude:
|
20
34
|
- 'lib/skunk/cli/application.rb'
|
21
35
|
|
22
|
-
# Offense count:
|
36
|
+
# Offense count: 7
|
23
37
|
# Cop supports --auto-correct.
|
24
38
|
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
25
39
|
# URISchemes: http, https
|
26
40
|
Metrics/LineLength:
|
27
|
-
Max:
|
41
|
+
Max: 96
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to make participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
9
|
+
level of experience, education, socio-economic status, nationality, personal
|
10
|
+
appearance, race, religion, or sexual identity and orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies within all project spaces, and it also applies when
|
49
|
+
an individual is representing the project or its community in public spaces.
|
50
|
+
Examples of representing a project or community include using an official
|
51
|
+
project e-mail address, posting via an official social media account, or acting
|
52
|
+
as an appointed representative at an online or offline event. Representation of
|
53
|
+
a project may be further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at oss@ombulabs.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
72
|
+
|
73
|
+
[homepage]: https://www.contributor-covenant.org
|
74
|
+
|
75
|
+
For answers to common questions about this code of conduct, see
|
76
|
+
https://www.contributor-covenant.org/faq
|
77
|
+
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
skunk (0.
|
5
|
-
rubycritic
|
4
|
+
skunk (0.3.0)
|
5
|
+
rubycritic (~> 4.2.1)
|
6
6
|
terminal-table (~> 1.8.0)
|
7
7
|
|
8
8
|
GEM
|
@@ -36,7 +36,7 @@ GEM
|
|
36
36
|
ruby_parser (~> 3.1, > 3.1.0)
|
37
37
|
sexp_processor (~> 4.8)
|
38
38
|
ice_nine (0.11.2)
|
39
|
-
jaro_winkler (1.5.
|
39
|
+
jaro_winkler (1.5.4)
|
40
40
|
json (2.2.0)
|
41
41
|
kwalify (0.7.2)
|
42
42
|
launchy (2.4.3)
|
@@ -44,7 +44,7 @@ GEM
|
|
44
44
|
minitest (5.8.5)
|
45
45
|
minitest-around (0.5.0)
|
46
46
|
minitest (~> 5.0)
|
47
|
-
parallel (1.
|
47
|
+
parallel (1.19.0)
|
48
48
|
parser (2.6.5.0)
|
49
49
|
ast (~> 2.4.0)
|
50
50
|
path_expander (1.1.0)
|
@@ -52,13 +52,13 @@ GEM
|
|
52
52
|
public_suffix (4.0.1)
|
53
53
|
rainbow (3.0.0)
|
54
54
|
rake (10.5.0)
|
55
|
-
reek (5.4.
|
55
|
+
reek (5.4.1)
|
56
56
|
codeclimate-engine-rb (~> 0.4.0)
|
57
57
|
kwalify (~> 0.7.0)
|
58
58
|
parser (>= 2.5.0.0, < 2.7, != 2.5.1.1)
|
59
59
|
psych (~> 3.1.0)
|
60
60
|
rainbow (>= 2.0, < 4.0)
|
61
|
-
rubocop (0.
|
61
|
+
rubocop (0.76.0)
|
62
62
|
jaro_winkler (~> 1.5.1)
|
63
63
|
parallel (~> 1.10)
|
64
64
|
parser (>= 2.6)
|
@@ -66,9 +66,9 @@ GEM
|
|
66
66
|
ruby-progressbar (~> 1.7)
|
67
67
|
unicode-display_width (>= 1.4.0, < 1.7)
|
68
68
|
ruby-progressbar (1.10.1)
|
69
|
-
ruby_parser (3.14.
|
69
|
+
ruby_parser (3.14.1)
|
70
70
|
sexp_processor (~> 4.9)
|
71
|
-
rubycritic
|
71
|
+
rubycritic (4.2.2)
|
72
72
|
flay (~> 2.8)
|
73
73
|
flog (~> 4.4)
|
74
74
|
launchy (= 2.4.3)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2019 Ernesto Tagwerker
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Skunk
|
2
2
|
|
3
|
+
[](code-of-conduct.md) [](https://travis-ci.org/fastruby/skunk) [](https://codeclimate.com/github/fastruby/skunk/maintainability)
|
4
|
+
|
3
5
|
A RubyCritic extension to calculate StinkScore for a file or project.
|
4
6
|
|
5
7
|
## What is the StinkScore?
|
6
8
|
|
7
|
-
The StinkScore is a value that
|
9
|
+
The StinkScore is a value that assesses the quality of a module. It takes into
|
8
10
|
account:
|
9
11
|
|
10
12
|
- Code Quality
|
@@ -12,7 +14,16 @@ account:
|
|
12
14
|
- Churn
|
13
15
|
- Code Coverage
|
14
16
|
|
15
|
-
The
|
17
|
+
The main goal of the StinkScore is to serve as a compass in your next
|
18
|
+
refactoring adventure. It will help you answer these questions:
|
19
|
+
|
20
|
+
- What can I do to pay off technical debt?
|
21
|
+
- What are the most complicated files with the least code coverage?
|
22
|
+
- What are good candidates for your next test-writing efforts?
|
23
|
+
- What are good candidates for your nest refactoring efforts?
|
24
|
+
|
25
|
+
The formula is not perfect and it is certainly controversial, so any feedback is
|
26
|
+
welcome as a new issue!
|
16
27
|
|
17
28
|
## Installation
|
18
29
|
|
@@ -32,7 +43,13 @@ Or install it yourself as:
|
|
32
43
|
|
33
44
|
## Usage
|
34
45
|
|
35
|
-
|
46
|
+
### Getting a sorted list of stinkiest files
|
47
|
+
|
48
|
+
To get the best results, make sure that you have `coverage/.resultset.json` in
|
49
|
+
your application directory. That way `skunk` knows what's the status of your
|
50
|
+
test suite + code coverage.
|
51
|
+
|
52
|
+
Then simply run:
|
36
53
|
|
37
54
|
```
|
38
55
|
skunk
|
@@ -84,11 +101,60 @@ StinkScore Average: 0.47100769230769230769230769231e2
|
|
84
101
|
Worst StinkScore: 166.44 (lib/skunk/cli/commands/default.rb)
|
85
102
|
```
|
86
103
|
|
87
|
-
The command will run `rubycritic
|
88
|
-
|
104
|
+
The command will run `rubycritic` and it will try to load code coverage data
|
105
|
+
from your `.resultset.json` file.
|
89
106
|
|
90
107
|
Skunk's report will be in the console. Use it wisely. :)
|
91
108
|
|
109
|
+
### Comparing one branch vs. another
|
110
|
+
|
111
|
+
Simply run:
|
112
|
+
|
113
|
+
```
|
114
|
+
skunk -b <target-branch-name>
|
115
|
+
```
|
116
|
+
|
117
|
+
Then get a StinkScore average comparison:
|
118
|
+
|
119
|
+
```
|
120
|
+
$ skunk -b master
|
121
|
+
Switched to branch 'master'
|
122
|
+
running flay smells
|
123
|
+
..
|
124
|
+
running flog smells
|
125
|
+
..............
|
126
|
+
running reek smells
|
127
|
+
..............
|
128
|
+
running complexity
|
129
|
+
..............
|
130
|
+
running attributes
|
131
|
+
..............
|
132
|
+
running churn
|
133
|
+
..............
|
134
|
+
running simple_cov
|
135
|
+
..............
|
136
|
+
Switched to branch 'feature/compare'
|
137
|
+
running flay smells
|
138
|
+
..
|
139
|
+
running flog smells
|
140
|
+
.................
|
141
|
+
running reek smells
|
142
|
+
.................
|
143
|
+
running complexity
|
144
|
+
.................
|
145
|
+
running attributes
|
146
|
+
.................
|
147
|
+
running churn
|
148
|
+
.................
|
149
|
+
running simple_cov
|
150
|
+
.................
|
151
|
+
Base branch (master) average stink score: 290.53999999999996
|
152
|
+
Feature branch (feature/compare) average stink score: 340.3005882352941
|
153
|
+
Score: 340.3
|
154
|
+
```
|
155
|
+
|
156
|
+
This should give you an idea if you're moving in the right direction or not.
|
157
|
+
|
92
158
|
## Known Issues
|
93
159
|
|
94
160
|
The StinkScore should be calculated per method. This would provide a more accurate
|
@@ -113,4 +179,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
113
179
|
|
114
180
|
## Contributing
|
115
181
|
|
116
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/fastruby/skunk.
|
182
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/fastruby/skunk/issues.
|
data/bin/console
CHANGED
@@ -6,7 +6,7 @@ module Skunk
|
|
6
6
|
module Cli
|
7
7
|
# Knows how to calculate the command that was request by the CLI user
|
8
8
|
class CommandFactory < RubyCritic::CommandFactory
|
9
|
-
COMMAND_CLASS_MODES = %i[version help default].freeze
|
9
|
+
COMMAND_CLASS_MODES = %i[version help default compare].freeze
|
10
10
|
|
11
11
|
# Returns the command class based on the command that was executed
|
12
12
|
#
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubycritic/commands/compare"
|
4
|
+
require "skunk/rubycritic/analysed_modules_collection"
|
5
|
+
|
6
|
+
# nodoc #
|
7
|
+
module Skunk
|
8
|
+
module Command
|
9
|
+
# Knows how to compare two branches and their stink score average
|
10
|
+
class Compare < RubyCritic::Command::Compare
|
11
|
+
# switch branch and analyse files but don't generate a report
|
12
|
+
def analyse_branch(branch)
|
13
|
+
::RubyCritic::SourceControlSystem::Git.switch_branch(::RubyCritic::Config.send(branch))
|
14
|
+
critic = critique(branch)
|
15
|
+
::RubyCritic::Config.send(:"#{branch}_score=", critic.stink_score_average)
|
16
|
+
::RubyCritic::Config.root = branch_directory(branch)
|
17
|
+
end
|
18
|
+
|
19
|
+
# generate report only for modified files but don't report it
|
20
|
+
def analyse_modified_files
|
21
|
+
modified_files = ::RubyCritic::Config
|
22
|
+
.feature_branch_collection
|
23
|
+
.where(::RubyCritic::SourceControlSystem::Git.modified_files)
|
24
|
+
::RubyCritic::AnalysedModulesCollection.new(modified_files.map(&:path),
|
25
|
+
modified_files)
|
26
|
+
::RubyCritic::Config.root = "#{::RubyCritic::Config.root}/compare"
|
27
|
+
end
|
28
|
+
|
29
|
+
# create a txt file with the branch score details
|
30
|
+
def build_details
|
31
|
+
details = "Base branch (#{::RubyCritic::Config.base_branch}) "\
|
32
|
+
"average stink score: #{::RubyCritic::Config.base_branch_score} \n"\
|
33
|
+
"Feature branch (#{::RubyCritic::Config.feature_branch}) "\
|
34
|
+
"average stink score: #{::RubyCritic::Config.feature_branch_score} \n"
|
35
|
+
File.open(build_details_path, "w") { |file| file.write(details) }
|
36
|
+
puts details
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_details_path
|
40
|
+
"#{::RubyCritic::Config.compare_root_directory}/build_details.txt"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -20,16 +20,13 @@ module Skunk
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def execute
|
23
|
+
RubyCritic::Config.formats = []
|
24
|
+
|
23
25
|
report(critique)
|
24
26
|
status_reporter
|
25
27
|
end
|
26
28
|
|
27
|
-
def critique
|
28
|
-
RubyCritic::AnalysersRunner.new(paths).run
|
29
|
-
end
|
30
|
-
|
31
29
|
def report(analysed_modules)
|
32
|
-
RubyCritic::Reporter.generate_report(analysed_modules)
|
33
30
|
status_reporter.analysed_modules = analysed_modules
|
34
31
|
status_reporter.score = analysed_modules.score
|
35
32
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "erb"
|
3
4
|
require "rubycritic/commands/status_reporter"
|
4
5
|
require "terminal-table"
|
5
6
|
|
@@ -11,6 +12,15 @@ module Skunk
|
|
11
12
|
|
12
13
|
HEADINGS = %w[file stink_score churn_times_cost churn cost coverage].freeze
|
13
14
|
|
15
|
+
TEMPLATE = ERB.new(<<-TEMPL
|
16
|
+
<%= ttable %>\n
|
17
|
+
StinkScore Total: <%= total_stink_score %>
|
18
|
+
Modules Analysed: <%= analysed_modules_count %>
|
19
|
+
StinkScore Average: <%= stink_score_average %>
|
20
|
+
<% if worst %>Worst StinkScore: <%= worst.stink_score %> (<%= worst.pathname %>)<% end %>
|
21
|
+
TEMPL
|
22
|
+
)
|
23
|
+
|
14
24
|
# Returns a status message with a table of all analysed_modules and
|
15
25
|
# a stink score average
|
16
26
|
def update_status_message
|
@@ -18,12 +28,7 @@ module Skunk
|
|
18
28
|
|
19
29
|
ttable = Terminal::Table.new(opts)
|
20
30
|
|
21
|
-
@status_message =
|
22
|
-
|
23
|
-
@status_message += "StinkScore Total: #{total_stink_score}\n"
|
24
|
-
@status_message += "Modules Analysed: #{analysed_modules_count}\n"
|
25
|
-
@status_message += "StinkScore Average: #{stink_score}\n"
|
26
|
-
@status_message += "Worst StinkScore: #{worst.stink_score} (#{worst.pathname})\n" if worst
|
31
|
+
@status_message = TEMPLATE.result(binding)
|
27
32
|
end
|
28
33
|
|
29
34
|
private
|
@@ -33,7 +38,9 @@ module Skunk
|
|
33
38
|
end
|
34
39
|
|
35
40
|
def non_test_modules
|
36
|
-
@non_test_modules ||= analysed_modules.reject
|
41
|
+
@non_test_modules ||= analysed_modules.reject do |a_module|
|
42
|
+
a_module.pathname.to_s.start_with?("test", "spec")
|
43
|
+
end
|
37
44
|
end
|
38
45
|
|
39
46
|
def worst
|
@@ -52,10 +59,10 @@ module Skunk
|
|
52
59
|
non_test_modules.map(&:churn_times_cost).sum
|
53
60
|
end
|
54
61
|
|
55
|
-
def
|
56
|
-
return 0 if analysed_modules_count
|
62
|
+
def stink_score_average
|
63
|
+
return 0 if analysed_modules_count.zero?
|
57
64
|
|
58
|
-
total_stink_score.to_d / analysed_modules_count
|
65
|
+
(total_stink_score.to_d / analysed_modules_count).to_f
|
59
66
|
end
|
60
67
|
|
61
68
|
def table_options
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubycritic/core/analysed_modules_collection"
|
4
|
+
|
5
|
+
module RubyCritic
|
6
|
+
# nodoc #
|
7
|
+
class AnalysedModulesCollection
|
8
|
+
def stink_score_average
|
9
|
+
num_modules = @modules.size
|
10
|
+
if num_modules.positive?
|
11
|
+
map(&:stink_score).reduce(:+) / num_modules.to_f
|
12
|
+
else
|
13
|
+
0.0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/skunk/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubycritic/core/analysed_module"
|
4
|
+
|
5
|
+
module RubyCritic
|
6
|
+
# Monkey-patches RubyCritic::AnalysedModule to add a stink_score method
|
7
|
+
class AnalysedModule
|
8
|
+
PERFECT_COVERAGE = 100
|
9
|
+
|
10
|
+
# Returns a numeric value that represents the stink_score of a module:
|
11
|
+
#
|
12
|
+
# If module is perfectly covered, stink score is the same as the
|
13
|
+
# `churn_times_cost`
|
14
|
+
#
|
15
|
+
# If module has no coverage, stink score is a penalized value of
|
16
|
+
# `churn_times_cost`
|
17
|
+
#
|
18
|
+
# For now the stink_score is calculated by multiplying `churn_times_cost`
|
19
|
+
# times the lack of coverage.
|
20
|
+
#
|
21
|
+
# For example:
|
22
|
+
#
|
23
|
+
# When `churn_times_cost` is 100 and module is perfectly covered:
|
24
|
+
# stink_score => 100
|
25
|
+
#
|
26
|
+
# When `churn_times_cost` is 100 and module is not covered at all:
|
27
|
+
# stink_score => 100 * 100 = 10_000
|
28
|
+
#
|
29
|
+
# When `churn_times_cost` is 100 and module is covered at 75%:
|
30
|
+
# stink_score => 100 * 25 (percentage uncovered) = 2_500
|
31
|
+
#
|
32
|
+
# @return [Float]
|
33
|
+
def stink_score
|
34
|
+
return churn_times_cost.round(2) if coverage == PERFECT_COVERAGE
|
35
|
+
|
36
|
+
(churn_times_cost * (PERFECT_COVERAGE - coverage.to_i)).round(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the value of churn times cost.
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
42
|
+
def churn_times_cost
|
43
|
+
safe_churn = churn.positive? ? churn : 1
|
44
|
+
@churn_times_cost ||= safe_churn * cost
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/skunk.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.version = Skunk::VERSION
|
10
10
|
spec.authors = ["Ernesto Tagwerker"]
|
11
11
|
spec.email = ["ernesto+github@ombulabs.com"]
|
12
|
-
|
12
|
+
spec.licenses = ['MIT']
|
13
13
|
spec.summary = "A library to assess code quality vs. code coverage"
|
14
14
|
spec.description = "Knows how to calculate the StinkScore for a Ruby file"
|
15
15
|
spec.homepage = "https://github.com/fastruby/skunk"
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
37
|
spec.require_paths = ["lib"]
|
38
38
|
|
39
|
-
spec.add_dependency "rubycritic
|
39
|
+
spec.add_dependency "rubycritic", "~> 4.2.1"
|
40
40
|
spec.add_dependency "terminal-table", "~> 1.8.0"
|
41
41
|
|
42
42
|
spec.add_development_dependency "bundler", "~> 2.0"
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skunk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernesto Tagwerker
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: rubycritic
|
14
|
+
name: rubycritic
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.
|
19
|
+
version: 4.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.
|
26
|
+
version: 4.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: terminal-table
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,9 +176,12 @@ files:
|
|
176
176
|
- ".reek.yml"
|
177
177
|
- ".rubocop.yml"
|
178
178
|
- ".rubocop_todo.yml"
|
179
|
+
- ".travis.yml"
|
179
180
|
- CHANGELOG.md
|
181
|
+
- CODE_OF_CONDUCT.md
|
180
182
|
- Gemfile
|
181
183
|
- Gemfile.lock
|
184
|
+
- LICENSE.txt
|
182
185
|
- README.md
|
183
186
|
- Rakefile
|
184
187
|
- bin/console
|
@@ -188,15 +191,19 @@ files:
|
|
188
191
|
- lib/skunk/cli/application.rb
|
189
192
|
- lib/skunk/cli/command_factory.rb
|
190
193
|
- lib/skunk/cli/commands/base.rb
|
194
|
+
- lib/skunk/cli/commands/compare.rb
|
191
195
|
- lib/skunk/cli/commands/default.rb
|
192
196
|
- lib/skunk/cli/commands/help.rb
|
193
197
|
- lib/skunk/cli/commands/status_reporter.rb
|
194
198
|
- lib/skunk/cli/options.rb
|
195
199
|
- lib/skunk/rubycritic/analysed_module.rb
|
200
|
+
- lib/skunk/rubycritic/analysed_modules_collection.rb
|
196
201
|
- lib/skunk/version.rb
|
202
|
+
- samples/rubycritic/analysed_module.rb
|
197
203
|
- skunk.gemspec
|
198
204
|
homepage: https://github.com/fastruby/skunk
|
199
|
-
licenses:
|
205
|
+
licenses:
|
206
|
+
- MIT
|
200
207
|
metadata:
|
201
208
|
allowed_push_host: https://www.rubygems.org
|
202
209
|
homepage_uri: https://github.com/fastruby/skunk
|
@@ -217,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
224
|
- !ruby/object:Gem::Version
|
218
225
|
version: '0'
|
219
226
|
requirements: []
|
220
|
-
rubygems_version: 3.0.
|
227
|
+
rubygems_version: 3.0.6
|
221
228
|
signing_key:
|
222
229
|
specification_version: 4
|
223
230
|
summary: A library to assess code quality vs. code coverage
|