rubocop-minitest 0.18.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +0 -3
- data/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- data/.github/workflows/linting.yml +1 -1
- data/.github/workflows/spell_checking.yml +3 -3
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +31 -3
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +1 -1
- data/config/default.yml +34 -23
- data/docs/antora.yml +1 -1
- data/docs/modules/ROOT/pages/cops.adoc +2 -0
- data/docs/modules/ROOT/pages/cops_minitest.adoc +170 -42
- data/lib/rubocop/cop/minitest/assert_empty.rb +1 -2
- data/lib/rubocop/cop/minitest/assert_empty_literal.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_equal.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_in_delta.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_includes.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_instance_of.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_kind_of.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_match.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_nil.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_output.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_path_exists.rb +1 -2
- data/lib/rubocop/cop/minitest/assert_predicate.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_respond_to.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_silent.rb +1 -1
- data/lib/rubocop/cop/minitest/assert_truthy.rb +1 -2
- data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +1 -1
- data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +1 -1
- data/lib/rubocop/cop/minitest/duplicate_test_run.rb +84 -0
- data/lib/rubocop/cop/minitest/global_expectations.rb +1 -1
- data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +1 -1
- data/lib/rubocop/cop/minitest/multiple_assertions.rb +1 -1
- data/lib/rubocop/cop/minitest/no_assertions.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_empty.rb +1 -2
- data/lib/rubocop/cop/minitest/refute_equal.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_false.rb +1 -2
- data/lib/rubocop/cop/minitest/refute_in_delta.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_includes.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_instance_of.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_kind_of.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_match.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_nil.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_path_exists.rb +1 -2
- data/lib/rubocop/cop/minitest/refute_predicate.rb +1 -1
- data/lib/rubocop/cop/minitest/refute_respond_to.rb +1 -1
- data/lib/rubocop/cop/minitest/skip_ensure.rb +95 -0
- data/lib/rubocop/cop/minitest/test_method_name.rb +1 -1
- data/lib/rubocop/cop/minitest/unreachable_assertion.rb +1 -1
- data/lib/rubocop/cop/minitest/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/minitest_cops.rb +2 -0
- data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +2 -2
- data/lib/rubocop/cop/mixin/predicate_assertion_handleable.rb +6 -2
- data/lib/rubocop/minitest/assert_offense.rb +3 -3
- data/lib/rubocop/minitest/version.rb +1 -1
- data/relnotes/v0.12.0.md +1 -1
- data/relnotes/v0.15.2.md +1 -1
- data/relnotes/v0.19.0.md +5 -0
- data/relnotes/v0.19.1.md +5 -0
- data/relnotes/v0.20.0.md +13 -0
- data/relnotes/v0.9.0.md +1 -1
- data/rubocop-minitest.gemspec +1 -1
- metadata +10 -5
@@ -12,8 +12,7 @@
|
|
12
12
|
| -
|
13
13
|
|===
|
14
14
|
|
15
|
-
|
16
|
-
instead of using `assert(object.empty?)`.
|
15
|
+
Enforces the test to use `assert_empty` instead of using `assert(object.empty?)`.
|
17
16
|
|
18
17
|
=== Examples
|
19
18
|
|
@@ -44,7 +43,7 @@ assert_empty(object, 'message')
|
|
44
43
|
| 0.11
|
45
44
|
|===
|
46
45
|
|
47
|
-
|
46
|
+
Enforces the test to use `assert_empty`
|
48
47
|
instead of using `assert_equal([], object)` or `assert_equal({}, object)`.
|
49
48
|
|
50
49
|
=== Examples
|
@@ -71,7 +70,7 @@ assert_empty(object)
|
|
71
70
|
| -
|
72
71
|
|===
|
73
72
|
|
74
|
-
|
73
|
+
Enforces the use of `assert_equal(expected, actual)`
|
75
74
|
over `assert(expected == actual)`.
|
76
75
|
|
77
76
|
=== Examples
|
@@ -101,7 +100,7 @@ assert_equal("rubocop-minitest", actual)
|
|
101
100
|
| -
|
102
101
|
|===
|
103
102
|
|
104
|
-
|
103
|
+
Enforces the test to use `assert_in_delta`
|
105
104
|
instead of using `assert_equal` to compare floats.
|
106
105
|
|
107
106
|
=== Examples
|
@@ -133,7 +132,7 @@ assert_in_delta(0.2, actual, 0.001, 'message')
|
|
133
132
|
| -
|
134
133
|
|===
|
135
134
|
|
136
|
-
|
135
|
+
Enforces the test to use `assert_includes`
|
137
136
|
instead of using `assert(collection.include?(object))`.
|
138
137
|
|
139
138
|
=== Examples
|
@@ -165,7 +164,7 @@ assert_includes(collection, object, 'message')
|
|
165
164
|
| -
|
166
165
|
|===
|
167
166
|
|
168
|
-
|
167
|
+
Enforces the test to use `assert_instance_of(Class, object)`
|
169
168
|
over `assert(object.instance_of?(Class))`.
|
170
169
|
|
171
170
|
=== Examples
|
@@ -197,7 +196,7 @@ assert_instance_of(Class, object, 'message')
|
|
197
196
|
| -
|
198
197
|
|===
|
199
198
|
|
200
|
-
|
199
|
+
Enforces the test to use `assert_kind_of(Class, object)`
|
201
200
|
over `assert(object.kind_of?(Class))`.
|
202
201
|
|
203
202
|
=== Examples
|
@@ -229,7 +228,7 @@ assert_kind_of(Class, object, 'message')
|
|
229
228
|
| -
|
230
229
|
|===
|
231
230
|
|
232
|
-
|
231
|
+
Enforces the test to use `assert_match`
|
233
232
|
instead of using `assert(matcher.match(string))`.
|
234
233
|
|
235
234
|
=== Examples
|
@@ -261,7 +260,7 @@ assert_match(matcher, string, 'message')
|
|
261
260
|
| -
|
262
261
|
|===
|
263
262
|
|
264
|
-
|
263
|
+
Enforces the test to use `assert_nil` instead of using
|
265
264
|
`assert_equal(nil, something)`, `assert(something.nil?)`, or `assert_predicate(something, :nil?)`.
|
266
265
|
|
267
266
|
=== Examples
|
@@ -297,7 +296,7 @@ assert_nil(actual, 'message')
|
|
297
296
|
| -
|
298
297
|
|===
|
299
298
|
|
300
|
-
|
299
|
+
Checks for opportunities to use `assert_output`.
|
301
300
|
|
302
301
|
=== Examples
|
303
302
|
|
@@ -329,8 +328,7 @@ assert_output(expected) { puts object.method }
|
|
329
328
|
| -
|
330
329
|
|===
|
331
330
|
|
332
|
-
|
333
|
-
instead of using `assert(File.exist?(path))`.
|
331
|
+
Enforces the test to use `assert_path_exists` instead of using `assert(File.exist?(path))`.
|
334
332
|
|
335
333
|
=== Examples
|
336
334
|
|
@@ -361,7 +359,7 @@ assert_path_exists(path, 'message')
|
|
361
359
|
| -
|
362
360
|
|===
|
363
361
|
|
364
|
-
|
362
|
+
Enforces the test to use `assert_predicate`
|
365
363
|
instead of using `assert(obj.a_predicate_method?)`.
|
366
364
|
|
367
365
|
=== Examples
|
@@ -393,7 +391,7 @@ assert_predicate(obj, :one?, 'message')
|
|
393
391
|
| -
|
394
392
|
|===
|
395
393
|
|
396
|
-
|
394
|
+
Enforces the use of `assert_respond_to(object, :do_something)`
|
397
395
|
over `assert(object.respond_to?(:do_something))`.
|
398
396
|
|
399
397
|
=== Examples
|
@@ -427,7 +425,7 @@ assert_respond_to(self, :do_something)
|
|
427
425
|
| -
|
428
426
|
|===
|
429
427
|
|
430
|
-
|
428
|
+
Enforces the test to use `assert_silent { ... }`
|
431
429
|
instead of using `assert_output('', '') { ... }`.
|
432
430
|
|
433
431
|
=== Examples
|
@@ -457,8 +455,7 @@ assert_silent { puts object.do_something }
|
|
457
455
|
| -
|
458
456
|
|===
|
459
457
|
|
460
|
-
|
461
|
-
instead of using `assert_equal(true, actual)`.
|
458
|
+
Enforces the test to use `assert(actual)` instead of using `assert_equal(true, actual)`.
|
462
459
|
|
463
460
|
=== Examples
|
464
461
|
|
@@ -489,7 +486,7 @@ assert(actual, 'message')
|
|
489
486
|
| -
|
490
487
|
|===
|
491
488
|
|
492
|
-
|
489
|
+
Tries to detect when a user accidentally used
|
493
490
|
`assert` when they meant to use `assert_equal`.
|
494
491
|
|
495
492
|
=== Safety
|
@@ -523,7 +520,7 @@ assert(foo, 'message')
|
|
523
520
|
| -
|
524
521
|
|===
|
525
522
|
|
526
|
-
|
523
|
+
Checks for usage of assertions in lifecycle hooks.
|
527
524
|
|
528
525
|
=== Examples
|
529
526
|
|
@@ -544,6 +541,67 @@ class FooTest < Minitest::Test
|
|
544
541
|
end
|
545
542
|
----
|
546
543
|
|
544
|
+
== Minitest/DuplicateTestRun
|
545
|
+
|
546
|
+
|===
|
547
|
+
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
|
548
|
+
|
549
|
+
| Pending
|
550
|
+
| Yes
|
551
|
+
| No
|
552
|
+
| 0.19
|
553
|
+
| -
|
554
|
+
|===
|
555
|
+
|
556
|
+
If a Minitest class inherits from another class,
|
557
|
+
it will also inherit its methods causing Minitest to run the parent's tests methods twice.
|
558
|
+
|
559
|
+
This cop detects when there are two tests classes, one inherits from the other, and both have tests methods.
|
560
|
+
This cop will add an offense to the Child class in such a case.
|
561
|
+
|
562
|
+
=== Examples
|
563
|
+
|
564
|
+
[source,ruby]
|
565
|
+
----
|
566
|
+
# bad
|
567
|
+
class ParentTest < Minitest::Test
|
568
|
+
def test_parent # it will run this test twice.
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
class ChildTest < ParentTest
|
573
|
+
def test_child
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
# good
|
578
|
+
class ParentTest < Minitest::Test
|
579
|
+
def test_parent
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
class ChildTest < Minitest::Test
|
584
|
+
def test_child
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
# good
|
589
|
+
class ParentTest < Minitest::Test
|
590
|
+
end
|
591
|
+
|
592
|
+
class ChildTest
|
593
|
+
def test_child
|
594
|
+
end
|
595
|
+
|
596
|
+
def test_parent
|
597
|
+
end
|
598
|
+
end
|
599
|
+
----
|
600
|
+
|
601
|
+
=== References
|
602
|
+
|
603
|
+
* https://minitest.rubystyle.guide/#subclassing-test-cases
|
604
|
+
|
547
605
|
== Minitest/GlobalExpectations
|
548
606
|
|
549
607
|
|===
|
@@ -556,7 +614,7 @@ end
|
|
556
614
|
| 0.16
|
557
615
|
|===
|
558
616
|
|
559
|
-
|
617
|
+
Checks for deprecated global expectations
|
560
618
|
and autocorrects them to use expect format.
|
561
619
|
|
562
620
|
=== Examples
|
@@ -683,7 +741,7 @@ value { musts }.must_raise TypeError
|
|
683
741
|
| -
|
684
742
|
|===
|
685
743
|
|
686
|
-
|
744
|
+
Enforces correct order of expected and
|
687
745
|
actual arguments for `assert_equal`.
|
688
746
|
|
689
747
|
=== Examples
|
@@ -717,7 +775,7 @@ assert_equal [1, 2], foo, 'message'
|
|
717
775
|
| -
|
718
776
|
|===
|
719
777
|
|
720
|
-
|
778
|
+
Checks if test cases contain too many assertion calls.
|
721
779
|
The maximum allowed assertion calls is configurable.
|
722
780
|
|
723
781
|
=== Examples
|
@@ -768,7 +826,7 @@ end
|
|
768
826
|
| -
|
769
827
|
|===
|
770
828
|
|
771
|
-
|
829
|
+
Checks if test cases contain any assertion calls.
|
772
830
|
|
773
831
|
=== Examples
|
774
832
|
|
@@ -800,8 +858,7 @@ end
|
|
800
858
|
| -
|
801
859
|
|===
|
802
860
|
|
803
|
-
|
804
|
-
using `refute(object.empty?)`.
|
861
|
+
Enforces to use `refute_empty` instead of using `refute(object.empty?)`.
|
805
862
|
|
806
863
|
=== Examples
|
807
864
|
|
@@ -832,7 +889,7 @@ refute_empty(object, 'message')
|
|
832
889
|
| -
|
833
890
|
|===
|
834
891
|
|
835
|
-
|
892
|
+
Enforces the use of `refute_equal(expected, object)`
|
836
893
|
over `assert(expected != actual)` or `assert(! expected == actual)`.
|
837
894
|
|
838
895
|
=== Examples
|
@@ -863,8 +920,7 @@ refute_equal("rubocop-minitest", actual)
|
|
863
920
|
| -
|
864
921
|
|===
|
865
922
|
|
866
|
-
|
867
|
-
over `assert_equal(false, object)`.
|
923
|
+
Enforces the use of `refute(object)` over `assert_equal(false, object)`.
|
868
924
|
|
869
925
|
=== Examples
|
870
926
|
|
@@ -898,7 +954,7 @@ refute(actual, 'message')
|
|
898
954
|
| -
|
899
955
|
|===
|
900
956
|
|
901
|
-
|
957
|
+
Enforces the test to use `refute_in_delta`
|
902
958
|
instead of using `refute_equal` to compare floats.
|
903
959
|
|
904
960
|
=== Examples
|
@@ -930,7 +986,7 @@ refute_in_delta(0.2, actual, 0.001, 'message')
|
|
930
986
|
| -
|
931
987
|
|===
|
932
988
|
|
933
|
-
|
989
|
+
Enforces the test to use `refute_includes`
|
934
990
|
instead of using `refute(collection.include?(object))`.
|
935
991
|
|
936
992
|
=== Examples
|
@@ -962,7 +1018,7 @@ refute_includes(collection, object, 'message')
|
|
962
1018
|
| -
|
963
1019
|
|===
|
964
1020
|
|
965
|
-
|
1021
|
+
Enforces the use of `refute_instance_of(Class, object)`
|
966
1022
|
over `refute(object.instance_of?(Class))`.
|
967
1023
|
|
968
1024
|
=== Examples
|
@@ -994,7 +1050,7 @@ refute_instance_of(Class, object, 'message')
|
|
994
1050
|
| -
|
995
1051
|
|===
|
996
1052
|
|
997
|
-
|
1053
|
+
Enforces the use of `refute_kind_of(Class, object)`
|
998
1054
|
over `refute(object.kind_of?(Class))`.
|
999
1055
|
|
1000
1056
|
=== Examples
|
@@ -1026,7 +1082,7 @@ refute_kind_of(Class, object, 'message')
|
|
1026
1082
|
| -
|
1027
1083
|
|===
|
1028
1084
|
|
1029
|
-
|
1085
|
+
Enforces the test to use `refute_match`
|
1030
1086
|
instead of using `refute(matcher.match(string))`.
|
1031
1087
|
|
1032
1088
|
=== Examples
|
@@ -1058,7 +1114,7 @@ refute_match(matcher, string, 'message')
|
|
1058
1114
|
| -
|
1059
1115
|
|===
|
1060
1116
|
|
1061
|
-
|
1117
|
+
Enforces the test to use `refute_nil` instead of using
|
1062
1118
|
`refute_equal(nil, something)`, `refute(something.nil?)`, or `refute_predicate(something, :nil?)`.
|
1063
1119
|
|
1064
1120
|
=== Examples
|
@@ -1094,8 +1150,7 @@ refute_nil(actual, 'message')
|
|
1094
1150
|
| -
|
1095
1151
|
|===
|
1096
1152
|
|
1097
|
-
|
1098
|
-
instead of using `refute(File.exist?(path))`.
|
1153
|
+
Enforces the test to use `refute_path_exists` instead of using `refute(File.exist?(path))`.
|
1099
1154
|
|
1100
1155
|
=== Examples
|
1101
1156
|
|
@@ -1126,7 +1181,7 @@ refute_path_exists(path, 'message')
|
|
1126
1181
|
| -
|
1127
1182
|
|===
|
1128
1183
|
|
1129
|
-
|
1184
|
+
Enforces the test to use `refute_predicate`
|
1130
1185
|
instead of using `refute(obj.a_predicate_method?)`.
|
1131
1186
|
|
1132
1187
|
=== Examples
|
@@ -1158,7 +1213,7 @@ refute_predicate(obj, :one?, 'message')
|
|
1158
1213
|
| -
|
1159
1214
|
|===
|
1160
1215
|
|
1161
|
-
|
1216
|
+
Enforces the test to use `refute_respond_to(object, :do_something)`
|
1162
1217
|
over `refute(object.respond_to?(:do_something))`.
|
1163
1218
|
|
1164
1219
|
=== Examples
|
@@ -1180,6 +1235,79 @@ refute_respond_to(self, :do_something)
|
|
1180
1235
|
|
1181
1236
|
* https://minitest.rubystyle.guide#refute-respond-to
|
1182
1237
|
|
1238
|
+
== Minitest/SkipEnsure
|
1239
|
+
|
1240
|
+
|===
|
1241
|
+
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
|
1242
|
+
|
1243
|
+
| Pending
|
1244
|
+
| Yes
|
1245
|
+
| No
|
1246
|
+
| 0.20
|
1247
|
+
| -
|
1248
|
+
|===
|
1249
|
+
|
1250
|
+
Checks that `ensure` call even if `skip`. It is unexpected that `ensure` will be called when skipping test.
|
1251
|
+
If conditional `skip` is used, it checks that `ensure` is also called conditionally.
|
1252
|
+
|
1253
|
+
On the other hand, it accepts `skip` used in `rescue` because `ensure` may be teardown process to `begin`
|
1254
|
+
setup process.
|
1255
|
+
|
1256
|
+
=== Examples
|
1257
|
+
|
1258
|
+
[source,ruby]
|
1259
|
+
----
|
1260
|
+
# bad
|
1261
|
+
def test_skip
|
1262
|
+
skip 'This test is skipped.'
|
1263
|
+
|
1264
|
+
assert 'foo'.present?
|
1265
|
+
ensure
|
1266
|
+
do_something
|
1267
|
+
end
|
1268
|
+
|
1269
|
+
# bad
|
1270
|
+
def test_conditional_skip
|
1271
|
+
skip 'This test is skipped.' if condition
|
1272
|
+
|
1273
|
+
assert do_something
|
1274
|
+
ensure
|
1275
|
+
do_teardown
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
# good
|
1279
|
+
def test_skip
|
1280
|
+
skip 'This test is skipped.'
|
1281
|
+
|
1282
|
+
begin
|
1283
|
+
assert 'foo'.present?
|
1284
|
+
ensure
|
1285
|
+
do_something
|
1286
|
+
end
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
# good
|
1290
|
+
def test_conditional_skip
|
1291
|
+
skip 'This test is skipped.' if condition
|
1292
|
+
|
1293
|
+
assert do_something
|
1294
|
+
ensure
|
1295
|
+
if condition
|
1296
|
+
do_teardown
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
# good
|
1301
|
+
def test_skip_is_used_in_rescue
|
1302
|
+
do_setup
|
1303
|
+
assert do_something
|
1304
|
+
rescue
|
1305
|
+
skip 'This test is skipped.'
|
1306
|
+
ensure
|
1307
|
+
do_teardown
|
1308
|
+
end
|
1309
|
+
----
|
1310
|
+
|
1183
1311
|
== Minitest/TestMethodName
|
1184
1312
|
|
1185
1313
|
|===
|
@@ -1192,7 +1320,7 @@ refute_respond_to(self, :do_something)
|
|
1192
1320
|
| -
|
1193
1321
|
|===
|
1194
1322
|
|
1195
|
-
|
1323
|
+
Enforces that test method names start with `test_` prefix.
|
1196
1324
|
It aims to prevent tests that aren't executed by forgetting to start test method name with `test_`.
|
1197
1325
|
|
1198
1326
|
=== Examples
|
@@ -1232,7 +1360,7 @@ end
|
|
1232
1360
|
| -
|
1233
1361
|
|===
|
1234
1362
|
|
1235
|
-
|
1363
|
+
Checks for `assert_raises` has an assertion method at
|
1236
1364
|
the bottom of block because the assertion will be never reached.
|
1237
1365
|
|
1238
1366
|
=== Examples
|
@@ -1264,7 +1392,7 @@ assert_equal('foo', obj.bar)
|
|
1264
1392
|
| -
|
1265
1393
|
|===
|
1266
1394
|
|
1267
|
-
|
1395
|
+
Checks for a specified error in `assert_raises`.
|
1268
1396
|
|
1269
1397
|
=== Examples
|
1270
1398
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Minitest
|
6
|
-
#
|
6
|
+
# Enforces the test to use `assert_nil` instead of using
|
7
7
|
# `assert_equal(nil, something)`, `assert(something.nil?)`, or `assert_predicate(something, :nil?)`.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Minitest
|
6
|
-
#
|
7
|
-
# instead of using `assert(File.exist?(path))`.
|
6
|
+
# Enforces the test to use `assert_path_exists` instead of using `assert(File.exist?(path))`.
|
8
7
|
#
|
9
8
|
# @example
|
10
9
|
# # bad
|
@@ -3,8 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Minitest
|
6
|
-
#
|
7
|
-
# instead of using `assert_equal(true, actual)`.
|
6
|
+
# Enforces the test to use `assert(actual)` instead of using `assert_equal(true, actual)`.
|
8
7
|
#
|
9
8
|
# @example
|
10
9
|
# # bad
|