gurkencheck 0.0.6 → 0.0.7

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.
Files changed (57) hide show
  1. package/README.md +115 -3
  2. package/dist/exit-codes.d.ts +10 -0
  3. package/dist/exit-codes.d.ts.map +1 -0
  4. package/dist/exit-codes.js +10 -0
  5. package/dist/exit-codes.js.map +1 -0
  6. package/dist/index.d.ts +10 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +6 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/main.d.ts.map +1 -1
  11. package/dist/main.js +12 -6
  12. package/dist/main.js.map +1 -1
  13. package/dist/stats/collect.d.ts +23 -0
  14. package/dist/stats/collect.d.ts.map +1 -0
  15. package/dist/stats/collect.js +219 -0
  16. package/dist/stats/collect.js.map +1 -0
  17. package/dist/stats/command.d.ts +3 -0
  18. package/dist/stats/command.d.ts.map +1 -0
  19. package/dist/stats/command.js +113 -0
  20. package/dist/stats/command.js.map +1 -0
  21. package/dist/stats/format/index.d.ts +25 -0
  22. package/dist/stats/format/index.d.ts.map +1 -0
  23. package/dist/stats/format/index.js +25 -0
  24. package/dist/stats/format/index.js.map +1 -0
  25. package/dist/stats/format/json.d.ts +10 -0
  26. package/dist/stats/format/json.d.ts.map +1 -0
  27. package/dist/stats/format/json.js +5 -0
  28. package/dist/stats/format/json.js.map +1 -0
  29. package/dist/stats/format/markdown.d.ts +8 -0
  30. package/dist/stats/format/markdown.d.ts.map +1 -0
  31. package/dist/stats/format/markdown.js +123 -0
  32. package/dist/stats/format/markdown.js.map +1 -0
  33. package/dist/stats/format/shared.d.ts +34 -0
  34. package/dist/stats/format/shared.d.ts.map +1 -0
  35. package/dist/stats/format/shared.js +37 -0
  36. package/dist/stats/format/shared.js.map +1 -0
  37. package/dist/stats/format/text.d.ts +5 -0
  38. package/dist/stats/format/text.d.ts.map +1 -0
  39. package/dist/stats/format/text.js +175 -0
  40. package/dist/stats/format/text.js.map +1 -0
  41. package/dist/stats/index.d.ts +21 -0
  42. package/dist/stats/index.d.ts.map +1 -0
  43. package/dist/stats/index.js +17 -0
  44. package/dist/stats/index.js.map +1 -0
  45. package/dist/stats/normalise.d.ts +38 -0
  46. package/dist/stats/normalise.d.ts.map +1 -0
  47. package/dist/stats/normalise.js +65 -0
  48. package/dist/stats/normalise.js.map +1 -0
  49. package/dist/stats/similar.d.ts +61 -0
  50. package/dist/stats/similar.d.ts.map +1 -0
  51. package/dist/stats/similar.js +173 -0
  52. package/dist/stats/similar.js.map +1 -0
  53. package/dist/stats/types.d.ts +159 -0
  54. package/dist/stats/types.d.ts.map +1 -0
  55. package/dist/stats/types.js +10 -0
  56. package/dist/stats/types.js.map +1 -0
  57. package/package.json +1 -1
package/README.md CHANGED
@@ -75,12 +75,16 @@ gurkencheck [options] <feature-files>
75
75
  -l, --language <code> dialect for files with no "# language:" header
76
76
  -h, --help show this message
77
77
  -v, --version show the version number
78
+
79
+ Commands:
80
+ stats [paths] report on the shape of your feature files,
81
+ rather than on what is wrong with them
78
82
  ```
79
83
 
80
84
  ## Rules
81
85
 
82
- There are 33 rules you switch on, covering naming, tags, indentation, structure and size,
83
- plus four that are always on because Gherkin itself refuses to read a file that breaks
86
+ There are 36 rules you switch on, covering naming, tags, indentation, structure and size,
87
+ plus five that are always on because Gherkin itself refuses to read a file that breaks
84
88
  them. Each one is documented at
85
89
  **[sebs.github.io/gurkencheck](https://sebs.github.io/gurkencheck/)** with a
86
90
  good and a bad example.
@@ -99,6 +103,114 @@ or a state plus that rule's own settings:
99
103
 
100
104
  Mistyped rule names and settings are reported before any file is read.
101
105
 
106
+ ## Statistics
107
+
108
+ `gurkencheck stats` describes a suite instead of judging it: what is in the files, how
109
+ much of the step vocabulary is shared, and where it has drifted apart.
110
+
111
+ ```sh
112
+ npx gurkencheck stats features
113
+ ```
114
+
115
+ ```
116
+ 124 files, 124 features, 811 test cases
117
+
118
+ Inventory
119
+ Features 124
120
+ Rules 18
121
+ Backgrounds 61
122
+ Scenarios 402
123
+ Scenario Outlines 57
124
+ Examples tables 61 409 rows
125
+ Steps 2314 as written
126
+ ...
127
+
128
+ Scenarios
129
+ Test cases 811 one per Scenario, one per Examples row
130
+ Steps per scenario min 1 median 5 p90 11 max 27 mean 5.5
131
+
132
+ Longest
133
+ 27 Checkout with every payment method features/checkout.feature:88
134
+ ...
135
+
136
+ Steps
137
+ Written 2314 Background steps included
138
+ Distinct 871 38% of all steps - lower is more reuse
139
+ Written once 512 59% of distinct steps
140
+ ...
141
+
142
+ Nearly the same (14 groups)
143
+ 9 i am logged in features/login.feature:4
144
+ 2 i'm logged in features/profile.feature:9
145
+ ```
146
+
147
+ Once it has run it exits `0`, whatever the numbers say; it exits `2` only when it could not
148
+ run at all, such as a format that does not exist or a `--top` that is not a whole number.
149
+ Statistics are for reading, not for failing a build — that is what the rules are for.
150
+
151
+ ```
152
+ gurkencheck stats [options] <feature-files>
153
+
154
+ -f, --format <format> output format: text, json, md (default: text)
155
+ -i, --ignore <globs> comma separated globs to skip
156
+ -l, --language <code> dialect for files with no "# language:" header
157
+ --top <n> how many entries each list shows (default: 10)
158
+ -h, --help show this message
159
+ ```
160
+
161
+ ### What the numbers mean
162
+
163
+ **Test cases** counts one per Scenario and one per row of every Examples table, because a
164
+ Scenario Outline with twelve rows is twelve tests. It is usually well above the number
165
+ people carry in their heads, and it is the one that predicts how long a run takes.
166
+
167
+ **Distinct steps** is the number to watch. Two steps count as one when they differ only in
168
+ what a step definition would capture anyway, so these are all the same step:
169
+
170
+ ```gherkin
171
+ Given I have 3 items in my cart
172
+ Given I have 17 items in my cart
173
+ Given I have 3 items in my cart.
174
+ ```
175
+
176
+ Numbers, `"quoted strings"` and `<placeholders>` are each replaced by a marker; case,
177
+ spacing and a trailing full stop or exclamation mark are ignored; and the keyword is left
178
+ out, so a `Given`
179
+ and an `And` of the same text are one step. Single quotes are left alone — `the user's
180
+ cart is 'empty'` has three of them, and pairing them up would eat half the sentence.
181
+
182
+ A low share of distinct steps means the team shares a vocabulary. A high one means
183
+ everybody invents their own phrasing, and the step definitions rot.
184
+
185
+ **Nearly the same** groups steps a few single-character edits apart: `I am logged in`
186
+ against `I'm logged in`, or a `<placeholder>` against a value written in its place. Those
187
+ are one behaviour costing two step definitions. The budget is at most three edits, and no
188
+ more than about a seventh of the longer of the two, so a short step is allowed only one;
189
+ steps under eight characters are left out altogether. That is deliberately tight — further
190
+ apart than that and a step is a different sentence rather than the same one spelled two
191
+ ways.
192
+
193
+ **Written once** lists the steps used exactly once. Some are genuine; most are a phrasing
194
+ somebody invented because they could not find the one that already existed.
195
+
196
+ **Untagged scenarios** counts the scenarios carrying no tag of their own, none on their
197
+ Examples tables, and none inherited from their Feature or Rule, and so reachable by no tag
198
+ expression.
199
+
200
+ Files the parser refuses are listed at the end rather than counted, because half a broken
201
+ file would quietly make every number wrong.
202
+
203
+ ### Keeping a record
204
+
205
+ `--format json` writes the whole dataset, with none of the lists cut short, indented so
206
+ that two runs can be diffed:
207
+
208
+ ```sh
209
+ npx gurkencheck stats features --format json > stats.json
210
+ ```
211
+
212
+ `--format md` writes the same report as Markdown tables, for pasting into a pull request.
213
+
102
214
  ## Reporting to GitHub code scanning
103
215
 
104
216
  `--format sarif` writes a SARIF 2.1.0 log, which GitHub reads directly:
@@ -138,7 +250,7 @@ Write a comment in the feature file:
138
250
  | `gurkencheck-disable-file` | The whole file, wherever the comment appears |
139
251
 
140
252
  Name the rules you mean, separated by commas or spaces; a directive naming no rules covers
141
- all of them. Comments inside a doc string are text and are left alone. The four always-on
253
+ all of them. Comments inside a doc string are text and are left alone. The five always-on
142
254
  rules cannot be switched off this way — a file that breaks one of them cannot be read at
143
255
  all, so hiding the message would leave nothing in its place.
144
256
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * What the command line hands back to the shell.
3
+ */
4
+ /** Nothing to report. */
5
+ export declare const EXIT_OK = 0;
6
+ /** At least one finding serious enough to fail the run. Warnings alone do not. */
7
+ export declare const EXIT_LINT_ERRORS = 1;
8
+ /** The command could not run: bad arguments, missing or invalid config. */
9
+ export declare const EXIT_USAGE = 2;
10
+ //# sourceMappingURL=exit-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yBAAyB;AACzB,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,2EAA2E;AAC3E,eAAO,MAAM,UAAU,IAAI,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * What the command line hands back to the shell.
3
+ */
4
+ /** Nothing to report. */
5
+ export const EXIT_OK = 0;
6
+ /** At least one finding serious enough to fail the run. Warnings alone do not. */
7
+ export const EXIT_LINT_ERRORS = 1;
8
+ /** The command could not run: bad arguments, missing or invalid config. */
9
+ export const EXIT_USAGE = 2;
10
+ //# sourceMappingURL=exit-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AAEzB,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -29,11 +29,21 @@ export type { ParseResult } from './gherkin/parse.ts';
29
29
  export { getNeutralKeyword, getNodeType } from './gherkin/keywords.ts';
30
30
  export { DEFAULT_LANGUAGE, detectLanguage, getDialect, isKnownLanguage } from './gherkin/dialects.ts';
31
31
  export { backgroundsOf, rulesOf, scenariosOf, stepContainersOf } from './gherkin/traverse.ts';
32
+ export { EXIT_LINT_ERRORS, EXIT_OK, EXIT_USAGE } from './exit-codes.ts';
32
33
  export { countBySeverity, hasErrors, lint } from './linter.ts';
33
34
  export type { LintOptions } from './linter.ts';
34
35
  export { readSuppressions } from './suppressions.ts';
35
36
  export type { Suppressions } from './suppressions.ts';
36
37
  export { getRuleSettings, getRuleSeverity, isRuleEnabled, loadRules, resetRules, runEnabledRules, } from './rules.ts';
37
38
  export { BUILT_IN_RULES } from './rules/index.ts';
39
+ export { collectStatistics, distribution } from './stats/collect.ts';
40
+ export type { CollectOptions } from './stats/collect.ts';
41
+ export { DEFAULT_SIMILARITY, boundedEditDistance, groupSimilar } from './stats/similar.ts';
42
+ export type { SimilarityOptions } from './stats/similar.ts';
43
+ export { NUMBER_MARKER, PLACEHOLDER_MARKER, STRING_MARKER, countWords, normaliseStepText, } from './stats/normalise.ts';
44
+ export { DEFAULT_STATS_FORMAT, DEFAULT_TOP, STATS_FORMATTERS, getStatsFormatter, toJson as statisticsToJson, toMarkdown, toText, } from './stats/format/index.ts';
45
+ export type { StatsFormatOptions, StatsFormatter } from './stats/format/index.ts';
46
+ export { runStats, statsUsage } from './stats/command.ts';
47
+ export type { Distribution, Inventory, KeywordMix, LanguageEntry, ScenarioRef, ScenarioStats, SimilarGroup, Statistics, StepEntry, StepStats, TagEntry, TagStats, UnreadableFile, } from './stats/types.ts';
38
48
  export type { Configuration, FeatureFile, FileResult, LintRule, RuleConfig, RuleError, RuleRegistry, RuleState, Severity, } from './types.ts';
39
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAC,wBAAwB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAC,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAC9F,YAAY,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAC,MAAM,EAAC,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,YAAY,EAAC,WAAW,EAAE,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAC,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACjG,YAAY,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,iBAAiB,EAAE,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAC,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAC,eAAe,EAAE,SAAS,EAAE,IAAI,EAAC,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,EACT,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,YAAY,EACV,aAAa,EACb,WAAW,EACX,UAAU,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -24,8 +24,14 @@ export { ALWAYS_ON_RULES, PARSER_RULES, parseFeature, readAndParseFile } from '.
24
24
  export { getNeutralKeyword, getNodeType } from './gherkin/keywords.js';
25
25
  export { DEFAULT_LANGUAGE, detectLanguage, getDialect, isKnownLanguage } from './gherkin/dialects.js';
26
26
  export { backgroundsOf, rulesOf, scenariosOf, stepContainersOf } from './gherkin/traverse.js';
27
+ export { EXIT_LINT_ERRORS, EXIT_OK, EXIT_USAGE } from './exit-codes.js';
27
28
  export { countBySeverity, hasErrors, lint } from './linter.js';
28
29
  export { readSuppressions } from './suppressions.js';
29
30
  export { getRuleSettings, getRuleSeverity, isRuleEnabled, loadRules, resetRules, runEnabledRules, } from './rules.js';
30
31
  export { BUILT_IN_RULES } from './rules/index.js';
32
+ export { collectStatistics, distribution } from './stats/collect.js';
33
+ export { DEFAULT_SIMILARITY, boundedEditDistance, groupSimilar } from './stats/similar.js';
34
+ export { NUMBER_MARKER, PLACEHOLDER_MARKER, STRING_MARKER, countWords, normaliseStepText, } from './stats/normalise.js';
35
+ export { DEFAULT_STATS_FORMAT, DEFAULT_TOP, STATS_FORMATTERS, getStatsFormatter, toJson as statisticsToJson, toMarkdown, toText, } from './stats/format/index.js';
36
+ export { runStats, statsUsage } from './stats/command.js';
31
37
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAC,wBAAwB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAE/E,OAAO,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAE9F,OAAO,EAAC,MAAM,EAAC,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC,OAAO,EAAC,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEjG,OAAO,EAAC,iBAAiB,EAAE,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAC,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAC,eAAe,EAAE,SAAS,EAAE,IAAI,EAAC,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,EACT,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAC,wBAAwB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAE/E,OAAO,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAE9F,OAAO,EAAC,MAAM,EAAC,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC,OAAO,EAAC,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEjG,OAAO,EAAC,iBAAiB,EAAE,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAC,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAC,gBAAgB,EAAE,OAAO,EAAE,UAAU,EAAC,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAC,eAAe,EAAE,SAAS,EAAE,IAAI,EAAC,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,EACT,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAC,iBAAiB,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAEnE,OAAO,EAAC,kBAAkB,EAAE,mBAAmB,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,IAAI,gBAAgB,EAC1B,UAAU,EACV,MAAM,GACP,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAC,MAAM,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AA6CA,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqFlE"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AA4CA,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FlE"}
package/dist/main.js CHANGED
@@ -6,19 +6,15 @@ import fs from 'node:fs';
6
6
  import { pathToFileURL } from 'node:url';
7
7
  import { parseArgs } from 'node:util';
8
8
  import { DEFAULT_CONFIG_FILE_NAME, readConfiguration } from './config-parser.js';
9
+ import { EXIT_LINT_ERRORS, EXIT_OK, EXIT_USAGE } from './exit-codes.js';
9
10
  import { DEFAULT_IGNORE_FILE_NAME, findFeatureFiles } from './feature-finder.js';
10
11
  import { DEFAULT_FORMAT, FORMATTERS, loadFormatter } from './formatters/index.js';
11
12
  import { isKnownLanguage } from './gherkin/dialects.js';
12
13
  import { hasErrors, lint } from './linter.js';
13
14
  import * as logger from './logger.js';
14
15
  import { loadRules } from './rules.js';
16
+ import { runStats } from './stats/command.js';
15
17
  import { version } from './version.js';
16
- /** Nothing to report. */
17
- const EXIT_OK = 0;
18
- /** At least one finding serious enough to fail the run. Warnings alone do not. */
19
- const EXIT_LINT_ERRORS = 1;
20
- /** The linter could not run: bad arguments, missing or invalid config. */
21
- const EXIT_USAGE = 2;
22
18
  function usage() {
23
19
  return [
24
20
  'Usage: gurkencheck [options] <feature-files>',
@@ -36,11 +32,21 @@ function usage() {
36
32
  ' -h, --help show this message',
37
33
  ' -v, --version show the version number',
38
34
  '',
35
+ 'Commands:',
36
+ ' stats [paths] report on the shape of your feature files,',
37
+ ' rather than on what is wrong with them',
38
+ '',
39
39
  'With no files given, the working directory is searched recursively.',
40
40
  'Documentation: https://sebs.github.io/gurkencheck/',
41
41
  ].join('\n');
42
42
  }
43
43
  export async function run(argv) {
44
+ // Subcommands are matched before the options are read, so that `stats` can
45
+ // accept a --format of its own without the two sets of names colliding.
46
+ // A directory really called `stats` is still lintable, as `./stats`.
47
+ if (argv[0] === 'stats') {
48
+ return runStats(argv.slice(1));
49
+ }
44
50
  let parsed;
45
51
  try {
46
52
  parsed = parseArgs({
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ParseResult } from '../gherkin/parse.ts';
2
+ import type { SimilarityOptions } from './similar.ts';
3
+ import type { Distribution, Statistics } from './types.ts';
4
+ export interface CollectOptions {
5
+ /** How alike two steps have to be to be reported as nearly the same. */
6
+ similarity?: SimilarityOptions;
7
+ }
8
+ /**
9
+ * A summary of a set of counts.
10
+ *
11
+ * The quantiles are nearest-rank: the median of an even set is the lower of
12
+ * the two middle values rather than the average of them, so every number in
13
+ * the summary is a number some scenario actually has.
14
+ */
15
+ export declare function distribution(values: readonly number[]): Distribution;
16
+ /**
17
+ * Counts a set of parsed feature files.
18
+ *
19
+ * Files the parser refused are listed rather than counted: half a broken file
20
+ * is worse than none of it, because the numbers would quietly be wrong.
21
+ */
22
+ export declare function collectStatistics(parsed: readonly ParseResult[], options?: CollectOptions): Statistics;
23
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/stats/collect.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAWrD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EAMZ,UAAU,EAGX,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAkBpE;AA2ID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,GAAE,cAAmB,GAC3B,UAAU,CA8FZ"}
@@ -0,0 +1,219 @@
1
+ import { getNeutralKeyword, resolvedStepKeywords } from '../gherkin/keywords.js';
2
+ import { backgroundsOf, rulesOf, scenariosOf, stepContainersOf, taggedNodesOf, } from '../gherkin/traverse.js';
3
+ import { countWords, normaliseStepText } from './normalise.js';
4
+ import { DEFAULT_SIMILARITY, groupSimilar } from './similar.js';
5
+ /**
6
+ * A summary of a set of counts.
7
+ *
8
+ * The quantiles are nearest-rank: the median of an even set is the lower of
9
+ * the two middle values rather than the average of them, so every number in
10
+ * the summary is a number some scenario actually has.
11
+ */
12
+ export function distribution(values) {
13
+ if (values.length === 0) {
14
+ return { count: 0, min: 0, median: 0, p90: 0, max: 0, mean: 0 };
15
+ }
16
+ const sorted = [...values].sort((a, b) => a - b);
17
+ const rank = (quantile) => sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(quantile * sorted.length) - 1))] ?? 0;
18
+ const sum = sorted.reduce((total, value) => total + value, 0);
19
+ return {
20
+ count: sorted.length,
21
+ min: sorted[0] ?? 0,
22
+ median: rank(0.5),
23
+ p90: rank(0.9),
24
+ max: sorted[sorted.length - 1] ?? 0,
25
+ mean: sum / sorted.length,
26
+ };
27
+ }
28
+ /** True when the node is a Scenario Outline rather than a plain Scenario. */
29
+ function isOutline(scenario, language) {
30
+ return getNeutralKeyword(scenario, language) === 'scenariooutline';
31
+ }
32
+ /**
33
+ * How many test cases a scenario stands for: one, or one per row of its
34
+ * Examples tables. This is how `max-scenarios-per-file` counts too, so the
35
+ * two never disagree about the size of a suite.
36
+ */
37
+ function testCases(scenario) {
38
+ if (scenario.examples.length === 0) {
39
+ return 1;
40
+ }
41
+ return scenario.examples.reduce((total, examples) => total + examples.tableBody.length, 0);
42
+ }
43
+ function tally(counts, key) {
44
+ counts.set(key, (counts.get(key) ?? 0) + 1);
45
+ }
46
+ /** Most used first, and alphabetically within an equal count. */
47
+ function byCountThenName(name) {
48
+ return (a, b) => {
49
+ if (a.count !== b.count) {
50
+ return b.count - a.count;
51
+ }
52
+ const left = name(a);
53
+ const right = name(b);
54
+ return left < right ? -1 : left > right ? 1 : 0;
55
+ };
56
+ }
57
+ /** Counts everything in one already parsed feature file. */
58
+ function collectFile(feature, file, into) {
59
+ const language = feature.language;
60
+ const { inventory } = into;
61
+ inventory.features += 1;
62
+ inventory.rules += [...rulesOf(feature)].length;
63
+ inventory.backgrounds += [...backgroundsOf(feature)].length;
64
+ for (const { scenario, rule } of scenariosOf(feature)) {
65
+ if (isOutline(scenario, language)) {
66
+ inventory.scenarioOutlines += 1;
67
+ }
68
+ else {
69
+ inventory.scenarios += 1;
70
+ }
71
+ for (const examples of scenario.examples) {
72
+ inventory.examplesTables += 1;
73
+ inventory.examplesRows += examples.tableBody.length;
74
+ }
75
+ into.effective += testCases(scenario);
76
+ into.stepsPerScenario.push(scenario.steps.length);
77
+ into.scenarios.push({
78
+ name: scenario.name,
79
+ file,
80
+ line: scenario.location.line,
81
+ steps: scenario.steps.length,
82
+ });
83
+ // A scenario with no tag anywhere on it and none to inherit cannot be
84
+ // picked out by any tag expression, however carefully the run is
85
+ // filtered. A tag on an Examples table counts: Cucumber puts it on every
86
+ // test case that table generates, so the scenario is reachable after all.
87
+ const selectable = scenario.tags.length > 0 ||
88
+ feature.tags.length > 0 ||
89
+ (rule?.tags.length ?? 0) > 0 ||
90
+ scenario.examples.some((examples) => examples.tags.length > 0);
91
+ if (!selectable) {
92
+ into.untagged += 1;
93
+ }
94
+ }
95
+ for (const { node } of stepContainersOf(feature)) {
96
+ const keywords = resolvedStepKeywords(node.steps, language);
97
+ node.steps.forEach((step, index) => {
98
+ inventory.steps += 1;
99
+ if (step.dataTable !== undefined) {
100
+ inventory.dataTables += 1;
101
+ }
102
+ if (step.docString !== undefined) {
103
+ inventory.docStrings += 1;
104
+ }
105
+ into.stepWords.push(countWords(step.text));
106
+ const keyword = keywords[index];
107
+ if (keyword === 'given' || keyword === 'when' || keyword === 'then') {
108
+ into.keywords[keyword] += 1;
109
+ }
110
+ else {
111
+ into.keywords.other += 1;
112
+ }
113
+ const text = normaliseStepText(step.text);
114
+ const seen = into.steps.get(text);
115
+ if (seen === undefined) {
116
+ into.steps.set(text, { count: 1, example: step.text.trim(), file, line: step.location.line });
117
+ }
118
+ else {
119
+ seen.count += 1;
120
+ }
121
+ });
122
+ }
123
+ for (const { node } of taggedNodesOf(feature)) {
124
+ for (const tag of node.tags) {
125
+ tally(into.tags, tag.name);
126
+ }
127
+ }
128
+ }
129
+ /**
130
+ * Counts a set of parsed feature files.
131
+ *
132
+ * Files the parser refused are listed rather than counted: half a broken file
133
+ * is worse than none of it, because the numbers would quietly be wrong.
134
+ */
135
+ export function collectStatistics(parsed, options = {}) {
136
+ const inventory = {
137
+ features: 0,
138
+ rules: 0,
139
+ backgrounds: 0,
140
+ scenarios: 0,
141
+ scenarioOutlines: 0,
142
+ examplesTables: 0,
143
+ examplesRows: 0,
144
+ steps: 0,
145
+ dataTables: 0,
146
+ docStrings: 0,
147
+ };
148
+ const into = {
149
+ inventory,
150
+ steps: new Map(),
151
+ keywords: { given: 0, when: 0, then: 0, other: 0 },
152
+ stepWords: [],
153
+ stepsPerScenario: [],
154
+ scenarios: [],
155
+ tags: new Map(),
156
+ effective: 0,
157
+ untagged: 0,
158
+ };
159
+ const unreadable = [];
160
+ const languages = new Map();
161
+ let readable = 0;
162
+ for (const result of parsed) {
163
+ const file = result.file.relativePath;
164
+ const failure = result.errors[0];
165
+ if (failure !== undefined) {
166
+ unreadable.push({ file, reason: failure.message, line: failure.line });
167
+ continue;
168
+ }
169
+ readable += 1;
170
+ // An empty file parses without complaint and holds nothing to count.
171
+ if (result.feature === undefined) {
172
+ continue;
173
+ }
174
+ tally(languages, result.feature.language);
175
+ collectFile(result.feature, file, into);
176
+ }
177
+ const vocabulary = [...into.steps]
178
+ .map(([text, sighting]) => ({ text, ...sighting }))
179
+ .sort(byCountThenName((entry) => entry.text));
180
+ const similar = groupSimilar(vocabulary, options.similarity ?? DEFAULT_SIMILARITY)
181
+ .map((members) => ({
182
+ members,
183
+ total: members.reduce((sum, member) => sum + member.count, 0),
184
+ }))
185
+ .sort((a, b) => b.total - a.total || b.members.length - a.members.length);
186
+ const tagVocabulary = [...into.tags]
187
+ .map(([name, count]) => ({ name, count }))
188
+ .sort(byCountThenName((entry) => entry.name));
189
+ return {
190
+ files: { total: parsed.length, parsed: readable, unreadable },
191
+ inventory,
192
+ scenarios: {
193
+ effective: into.effective,
194
+ stepsPerScenario: distribution(into.stepsPerScenario),
195
+ largest: [...into.scenarios].sort((a, b) => b.steps - a.steps),
196
+ },
197
+ steps: {
198
+ total: inventory.steps,
199
+ unique: vocabulary.length,
200
+ uniqueRatio: inventory.steps === 0 ? 0 : vocabulary.length / inventory.steps,
201
+ usedOnce: vocabulary.filter((entry) => entry.count === 1).length,
202
+ vocabulary,
203
+ similar,
204
+ keywords: into.keywords,
205
+ wordsPerStep: distribution(into.stepWords),
206
+ },
207
+ tags: {
208
+ total: tagVocabulary.reduce((sum, entry) => sum + entry.count, 0),
209
+ unique: tagVocabulary.length,
210
+ vocabulary: tagVocabulary,
211
+ usedOnce: tagVocabulary.filter((entry) => entry.count === 1).map((entry) => entry.name),
212
+ untaggedScenarios: into.untagged,
213
+ },
214
+ languages: [...languages]
215
+ .map(([code, files]) => ({ code, files }))
216
+ .sort((a, b) => b.files - a.files || (a.code < b.code ? -1 : 1)),
217
+ };
218
+ }
219
+ //# sourceMappingURL=collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.js","sourceRoot":"","sources":["../../src/stats/collect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function statsUsage(): string;
2
+ export declare function runStats(argv: readonly string[]): Promise<number>;
3
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/stats/command.ts"],"names":[],"mappings":"AAuBA,wBAAgB,UAAU,IAAI,MAAM,CAmBnC;AAqBD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkEvE"}