@suffolklitlab/alkiln 5.13.3-feat-random-3 → 5.13.3-feat-random-4

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.
@@ -76,7 +76,7 @@ jobs:
76
76
  DOCASSEMBLE_DEVELOPER_API_KEY: "${{ env.DOCASSEMBLE_DEVELOPER_API_KEY }}"
77
77
  #### Developer note: See https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
78
78
  #### You can probably leave this out
79
- MAX_RANDOM_TESTS_PER_SCENARIO: 10
79
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: 10
80
80
  # Internal: docassemble changes sometimes break @a11y tests. That is
81
81
  # a da problem, not ours. We will trigger these tests manually when we
82
82
  # want to check up on this.
package/CHANGELOG.md CHANGED
@@ -47,9 +47,9 @@ Format:
47
47
 
48
48
  ### Added
49
49
 
50
- - Add the `constrained random answers` Step. You must put the Step in a "constrained random test generator" Scenario which goes in a "constrained random test generator" file - a `.feature` file that starts with "alkiln_random". The file **MUST have ONLY 1 Scenario per generator file** at the moment. The Step is pretty strict. If there are irregularities, it will probably fail, but it will fail quickly. It is flexible about number of tests, though, and will default to 1. Closes [#962](https://github.com/SuffolkLITLab/ALKiln/issues/962).
51
- - Add `MAX_RANDOM_TESTS_PER_SCENARIO` optional environment variable for the above `constrained random answers` Step. Default value is `40` until we hear otherwise.
52
- - Regular tests that have incorrect syntax will fail more quickly now - very near the start. So will invalid "constrained random test generator" files. This will be a little slower for GitHub Sandbox tests right now, but still faster than it has been in the past. Closes [#972](https://github.com/SuffolkLITLab/ALKiln/issues/972).
50
+ - Add the `constrained random answers` Step. You must put the Step in a "constrained random test template" Scenario which goes in a "constrained random test template" file - a `.feature` file that starts with "alkiln_random". The file **MUST have ONLY 1 Scenario per template file** at the moment. The Step is pretty strict. If there are irregularities, it will probably fail, but it will fail quickly. It is flexible about number of tests, though, and will default to 1. Closes [#962](https://github.com/SuffolkLITLab/ALKiln/issues/962).
51
+ - Add `ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO` optional environment variable for the above `constrained random answers` Step. Default value is `40` until we hear otherwise.
52
+ - Regular tests that have incorrect syntax will fail more quickly now - very near the start. So will invalid "constrained random test template" files. This will be a little slower for GitHub Sandbox tests right now, but still faster than it has been in the past. Closes [#972](https://github.com/SuffolkLITLab/ALKiln/issues/972).
53
53
 
54
54
  ### Changed
55
55
 
package/action.yml CHANGED
@@ -33,7 +33,7 @@ inputs:
33
33
  description: "The version of docassemblecli to install."
34
34
  required: false
35
35
  default: "0.0.17"
36
- MAX_RANDOM_TESTS_PER_SCENARIO:
36
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO:
37
37
  description: "The maximum number of tests ALKiln will generate for every Scenario that can generate tests."
38
38
  required: false
39
39
  # Default will be internal to avoid duplication of data
@@ -72,7 +72,7 @@ runs:
72
72
  MAX_SECONDS_FOR_SETUP: ${{ inputs.MAX_SECONDS_FOR_SETUP }}
73
73
  SERVER_RELOAD_TIMEOUT_SECONDS: ${{ inputs.SERVER_RELOAD_TIMEOUT_SECONDS }}
74
74
  DOCASSEMBLECLI_VERSION: ${{ inputs.DOCASSEMBLECLI_VERSION }}
75
- MAX_RANDOM_TESTS_PER_SCENARIO: ${{ inputs.MAX_RANDOM_TESTS_PER_SCENARIO }}
75
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: ${{ inputs.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}
76
76
  shell: bash
77
77
  run: |
78
78
  log="💡 ALK0023 INFO: Set environment variables and create artifacts folder"
@@ -96,7 +96,7 @@ runs:
96
96
  echo "DOCASSEMBLE_DEVELOPER_API_KEY=$DOCASSEMBLE_DEVELOPER_API_KEY" >> $GITHUB_ENV
97
97
  echo "ALKILN_VERSION=$ALKILN_VERSION" >> $GITHUB_ENV
98
98
  echo "MAX_SECONDS_FOR_SETUP=$MAX_SECONDS_FOR_SETUP" >> $GITHUB_ENV
99
- echo "MAX_RANDOM_TESTS_PER_SCENARIO=$MAX_RANDOM_TESTS_PER_SCENARIO" >> $GITHUB_ENV
99
+ echo "ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO=$ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO" >> $GITHUB_ENV
100
100
  echo "SERVER_RELOAD_TIMEOUT_SECONDS=$SERVER_RELOAD_TIMEOUT_SECONDS" >> $GITHUB_ENV
101
101
  echo "DOCASSEMBLECLI_VERSION=$DOCASSEMBLECLI_VERSION" >> $GITHUB_ENV
102
102
  # Hard-coded internal ALKiln vars
@@ -106,7 +106,7 @@ runs:
106
106
  run: |
107
107
  log="💡 ALK0024 INFO: Confirm environment variables"
108
108
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
109
- vars_log='\nALKiln version is ${{ env.ALKILN_VERSION }}\nRepo is "${{ env.REPO_URL }}"\nBranch ref is "${{ env.BRANCH_PATH }}"\nCustom MAX_SECONDS_FOR_SETUP is "${{ env.MAX_SECONDS_FOR_SETUP }}"\nCustom SERVER_RELOAD_TIMEOUT_SECONDS is "${{ env.SERVER_RELOAD_TIMEOUT_SECONDS }}"\nCustom MAX_RANDOM_TESTS_PER_SCENARIO is "${{ env.MAX_RANDOM_TESTS_PER_SCENARIO }}"\n'
109
+ vars_log='\nALKiln version is ${{ env.ALKILN_VERSION }}\nRepo is "${{ env.REPO_URL }}"\nBranch ref is "${{ env.BRANCH_PATH }}"\nCustom MAX_SECONDS_FOR_SETUP is "${{ env.MAX_SECONDS_FOR_SETUP }}"\nCustom SERVER_RELOAD_TIMEOUT_SECONDS is "${{ env.SERVER_RELOAD_TIMEOUT_SECONDS }}"\nCustom ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO is "${{ env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}"\n'
110
110
  echo -e "$vars_log" >> "${{ env.DEBUG_PATH }}" && echo -e "$vars_log"
111
111
 
112
112
  # Install ALKiln during GitHub workflow
@@ -252,3 +252,27 @@ Scenario: I visit the zoo
252
252
 
253
253
  The AST doesn't have a list of lines. For examples, Scenarios and comments are in separate lists. The AST also stores line numbers, so we'd have to keep updating line numbers for every object, which adds complexity. We've currently decided that the more structured model isn't worth that complexity.
254
254
 
255
+
256
+ ## Ranges may not be that useful
257
+
258
+ Focused tests with actual thought out options are so useful. Take these examples:
259
+
260
+ ```gherkin
261
+ # ❌ Too broad: May miss important scenarios
262
+ Then ALKiln will stop at "end" with any combination of:
263
+ | var | possible values |
264
+ | income | 0..1000000 |
265
+ | assets | 0..1000000 |
266
+
267
+ # ✅ Better: Focused ranges with critical points
268
+ Then ALKiln will stop at "end" with any combination of:
269
+ | var | possible values |
270
+ | income | 0;; 30000;; 50000;; 75000;; 100000 |
271
+ | assets | 0;; 50000;; 100000;; 250000 |
272
+ ```
273
+
274
+ The first one will make a lot of useless tests. Is there a way to have a cake and eat it too? I'm not sure. Example:
275
+
276
+ ```
277
+ | income | 0..100;; 900..1000 |
278
+ ```
@@ -7,19 +7,18 @@ const get_Gherkin_AST = require(`./get_Gherkin_AST`);
7
7
  const get_error_stacks = require(`../utils/get_error_stacks`);
8
8
 
9
9
  /**
10
- * TODO: We might give various levels of categories for warnings. For example,
11
- * severe warnings (like "will skip the random test") vs. slight warnings
12
- * (like "missing number in constraints random test")
10
+ * TODO: Update ALKilnInThePlayground to let author download the generated
11
+ * tests. Also, store them in a unique location.
13
12
  * TODO: Post-MVP, don't repeat tests that the author has already created
14
13
  * TODO: Post-MVP, write Steps that warn about fore-Steps and constraints Steps
15
14
  * when they appear in a regular test. It probably means someone named the
16
15
  * file incorrectly.
17
- * Discuss: Require author to use "Generator Scenario:" as they keyword (Also
18
- * "Generator Scenario Outline:") (or "Scenario Generator", maybe harder to
19
- * scan) for 2 reasons. 1. Gets the vocab of "generator" in early (though
16
+ * Discuss: Require author to use "Template Scenario:" as they keyword (Also
17
+ * "Template Scenario Outline:") (or "Scenario Template", maybe harder to
18
+ * scan) for 2 reasons. 1. Gets the vocab of "template" in early (though
20
19
  * that doesn't match "constraints" Step, which is a whole other language
21
- * problem we haven't solved yet.) 2. Saying "MAX_RANDOM_TESTS_PER_SCENARIO"
22
- * is confusing when "Scenario" means different things - a generator
20
+ * problem we haven't solved yet.) 2. Saying "ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO"
21
+ * is confusing when "Scenario" means different things - a template
23
22
  * Scenario and a regular Scenario.
24
23
  * Discuss: Now that Log is less fragile and duplicated, shall we create a new
25
24
  * Log instance in here?
@@ -30,6 +29,9 @@ const get_error_stacks = require(`../utils/get_error_stacks`);
30
29
  * do that now, but without the icon.
31
30
  * Discuss: If/when we allow multiple Scenarios, research how we find the end
32
31
  * of a Scenario that ends in an `Example`.
32
+ * Discuss: We might give various levels of categories for warnings. For example,
33
+ * severe warnings (like "will skip the random test") vs. slight warnings
34
+ * (like "missing number in constraints random test")
33
35
  * */
34
36
 
35
37
  let log = null;
@@ -177,7 +179,7 @@ module.exports = class TestGenerator {
177
179
  let scenario_objs = doc_AST.feature.children;
178
180
  if ( !scenario_objs[0] ) {
179
181
  let syntax_error = log.error({ code: `ALK0235`, context: `generating files`, before: `\n\n`, },
180
- `The author's generator .feature file at "${ generator_path }" may be missing its Scenarios.`
182
+ `It looks like the author's template .feature file at "${ generator_path }" has 0 Scenarios.`
181
183
  );
182
184
  return { new_contents: null, errors: [new Error( syntax_error )]};
183
185
  }
@@ -185,7 +187,7 @@ module.exports = class TestGenerator {
185
187
 
186
188
  if ( scenario_objs.length > 1 ) {
187
189
  let too_many_scenarios = log.error({ code: `ALK0236`, context: `generating files`, },
188
- `A generator file can only have 1 generator Scenario. This one has ${ scenario_objs.length }.`
190
+ `A template file can only have 1 template Scenario. This one has ${ scenario_objs.length }.`
189
191
  );
190
192
  return { new_contents: ``, errors: [new Error( too_many_scenarios )] };
191
193
  }
@@ -250,7 +252,7 @@ module.exports = class TestGenerator {
250
252
  let errs_n_warns = new Misbehaviors();
251
253
 
252
254
  let strs_for_all_new_Scenarios = [];
253
- // Soon we want to be able to handle multiple generator Scenarios per file
255
+ // Soon we want to be able to handle multiple template Scenarios per file
254
256
  for ( let scenario_obj_i = 0; scenario_obj_i < scenario_objs.length; scenario_obj_i++ ) {
255
257
 
256
258
  errs_n_warns.reset_warnings();
@@ -370,11 +372,11 @@ module.exports = class TestGenerator {
370
372
 
371
373
  let got_fewer_tests_than_desired = new_test_bodies.length < num_to_make;
372
374
  if ( got_fewer_tests_than_desired ) {
373
- let warn_too_few = log.warn({ code: `ALK0260`, context: `generating files generator-scenario-level`, },
374
- `ALKiln could only make ${ new_test_bodies.length } *unique* tests out of the ${ num_to_make } the author wanted for this Scenario. Note that ALKiln compares all generated Scenarios with each other to make sure all are unique. This Scenario may be a duplicate of a Scenario generated by a previous generator. The Scenario:\n ${ scenario_description_for_logs({ scenario }) }`,
375
+ let warn_too_few = log.warn({ code: `ALK0260`, context: `generating files template-scenario-level`, },
376
+ `ALKiln could only make ${ new_test_bodies.length } *unique* tests out of the ${ num_to_make } the author wanted for this Scenario. Note that ALKiln compares all generated Scenarios with each other to make sure all are unique. This Scenario may be a duplicate of a Scenario generated from a previous template. The Scenario:\n ${ scenario_description_for_logs({ scenario }) }`,
375
377
  )
376
378
  // Discuss: Should we add more structure to Misbehaviors to give them
377
- // context levels (Feature, generator Scenario, generated Scenario)
379
+ // context levels (Feature, template Scenario, generated Scenario)
378
380
  misfits.add({ warnings: [ warn_too_few ] });
379
381
  }
380
382
 
@@ -493,7 +495,7 @@ function get_generator_AST({ file_text, generator_path }) {
493
495
 
494
496
  if ( generator_errors.length > 0 ) {
495
497
  let syntax_error = log.error({ code: `ALK0232`, context: `generating files`, before: `\n\n`, },
496
- `The author's generator .feature file at "${ generator_path }" has Gherkin syntax error(s). You might see more warnings above or below this one.\n`,
498
+ `The author's template .feature file at "${ generator_path }" has Gherkin syntax error(s). You might see more warnings above or below this one.\n`,
497
499
  ...get_error_stacks({ errors: generator_errors })
498
500
  );
499
501
  return { doc_AST: null, errors: [new Error( syntax_error )] };
@@ -503,14 +505,14 @@ function get_generator_AST({ file_text, generator_path }) {
503
505
 
504
506
  if ( !doc_AST.feature ) {
505
507
  let feature_error = log.error({ code: `ALK0233`, context: `generating files`, before: `\n\n`, },
506
- `The author's generator .feature file at "${ generator_path }" needs to include the \`Feature\` keyword.`
508
+ `The author's template .feature file at "${ generator_path }" needs to include the \`Feature\` keyword.`
507
509
  );
508
510
  return { doc_AST: null, errors: [new Error( feature_error )] };
509
511
  }
510
512
 
511
513
  // Should not get here
512
514
  let unknown_error = log.error({ code: `ALK0234`, context: `generating files`, before: `\n\n`, },
513
- `The author's generator .feature file at "${ generator_path }" ran into an unanticipated error when ALKiln tried to parse it. If you have a moment, we would love for you to send us your debug.txt.`
515
+ `The author's template .feature file at "${ generator_path }" ran into an unanticipated error when ALKiln tried to parse it. If you have a moment, we would love for you to send us your debug.txt.`
514
516
  );
515
517
  return { doc_AST, errors: [new Error( unknown_error )] };
516
518
  }
@@ -657,7 +659,7 @@ function get_fore_Steps({ scenario }) {
657
659
  if ( there_were_no_fore_Steps ) {
658
660
  misfits.add({ errors: [
659
661
  new Error( log.error({ code: `ALK0242`, context: `generating files`, },
660
- `A generator Scenario's first Step must say how many constrained random answers tests to make. The generator Scenario on line ${ scenario.location.line } is missing that Step. The Scenario's description is:\n${ description }`
662
+ `A template Scenario's first Step must say how many constrained random answers tests to make. The template Scenario on line ${ scenario.location.line } is missing that Step. The Scenario's description is:\n${ description }`
661
663
  ) )
662
664
  ] });
663
665
  } else {
@@ -724,7 +726,7 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
724
726
  // a way that is also maintainable?
725
727
  warnings.push(
726
728
  log.warn({ code: `ALK0238`, context: `generating files`, },
727
- `A generator Scenario has too many Steps that set the number of tests to make. ALKiln will use the final number Step it finds or calculates. The current Step:\n ${ text }`
729
+ `A template Scenario has too many Steps that set the number of tests to make. ALKiln will use the final number Step it finds or calculates. The current Step:\n ${ text }`
728
730
  )
729
731
  );
730
732
  }
@@ -735,7 +737,7 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
735
737
  if ( number_matcher === null ) {
736
738
  warnings.push(
737
739
  log.warn({ code: `ALK0239`, context: `generating files`, },
738
- `A generator Scenario is missing the number of tests to make. ALKiln will now make 1 constrained random answers test. The current Step:\n ${ text }`
740
+ `A template Scenario is missing the number of tests to make. ALKiln will now make 1 constrained random answers test. The current Step:\n ${ text }`
739
741
  )
740
742
  );
741
743
  return { num_to_make: 1, warnings, errors };
@@ -759,14 +761,14 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
759
761
  }
760
762
 
761
763
  let num_to_make = Math.min(
762
- session_vars.get_max_tests_per_generator_scenario(),
764
+ session_vars.get_max_tests_per_template_scenario(),
763
765
  user_num
764
766
  );
765
767
 
766
768
  if ( num_to_make !== user_num ) {
767
769
  warnings.push(
768
770
  log.warn({ code: `ALK0241`, context: `generating files`, },
769
- `The author asked to make ${ user_num } tests, but maximum allowed is ${ num_to_make }. ALKiln will now make ${ num_to_make } tests. If you want to increase the maximum, use the MAX_TESTS_PER_GENERATOR_SCENARIO environment variable. Read more about environment variables at https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#env-vars.`
771
+ `The author asked to make ${ user_num } tests, but maximum allowed is ${ num_to_make }. ALKiln will now make ${ num_to_make } tests. If you want to increase the maximum, use the ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO input. Read more about inputs at https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#workflow-inputs. The Step:\n ${ text }`
770
772
  )
771
773
  );
772
774
  }
@@ -1099,7 +1101,7 @@ function get_final_ids({ step_text }) {
1099
1101
  let ids = step_text.match( CAPTURE_QUESTION_IDS_REGEX );
1100
1102
 
1101
1103
  if ( ids === null ) {
1102
- let missing_ids_msg = `The constrained random answers Step is missing its question ids. ALKiln is unable to create random tests for this generator Scenario. The Step:\n${ step_text }`;
1104
+ let missing_ids_msg = `The constrained random answers Step is missing its question ids. ALKiln is unable to create random tests for this template Scenario. The Step:\n${ step_text }`;
1103
1105
  let error = log.error({ code: `ALK0250`, context: `generating files`, }, missing_ids_msg );
1104
1106
  errors.push(new Error( error ));
1105
1107
  }
@@ -1348,7 +1350,7 @@ function remove_warning_tag_placeholder({ new_text }) {
1348
1350
 
1349
1351
 
1350
1352
  function add_total_tests({ scenario_group_str, num_tests }) {
1351
- /** Paste in the total number of tests generated for this generator Scenario.
1353
+ /** Paste in the total number of tests generated for this template Scenario.
1352
1354
  *
1353
1355
  * @param {object} obj - Named arguments
1354
1356
  * @param {str} obj.scenario_group_str - The combined string of all the
@@ -1369,10 +1371,10 @@ function add_warnings_Scenario({ scenarios_str, warnings }) {
1369
1371
  * Scenarios. Basically, a whole-generator-scope warning.
1370
1372
  *
1371
1373
  * Discuss: Add a pre-group Scenario for every group of generated Scenarios
1372
- * identifying the generator Scenario of the subsequent new Scenarios.
1374
+ * identifying the template Scenario of the subsequent new Scenarios.
1373
1375
  * That is, even when there is no warning to give.
1374
1376
  *
1375
- * TODO: If/when we allow multiple generator Scenarios, use the ID here too
1377
+ * TODO: If/when we allow multiple template Scenarios, use the ID here too
1376
1378
  *
1377
1379
  * @param {object} obj - Named arguments
1378
1380
  * @param {str} obj.scenarios_str - The str of the already existing Scenarios
@@ -1381,7 +1383,7 @@ function add_warnings_Scenario({ scenarios_str, warnings }) {
1381
1383
  * @returns {str} - The text of the combined Scenarios.
1382
1384
  * */
1383
1385
  let tags = `@alkiln_extra_intro ${ ALKILN_WARNING_TAG }`;
1384
- let keyword_line = `Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.`;
1386
+ let keyword_line = `Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.`;
1385
1387
  let step_text = get_goofy_warnings_Step_text();
1386
1388
 
1387
1389
  let warnings_lines = warnings_as_list_of_lines({ warnings });
@@ -1435,7 +1437,7 @@ function get_warnings_docstring({ warnings_lines, indent }) {
1435
1437
  * */
1436
1438
  let doc_str_lines = [
1437
1439
  `"""`,
1438
- `――――― Generator file warnings ―――――`,
1440
+ `――――― Template file warnings ―――――`,
1439
1441
  ...warnings_lines,
1440
1442
  `―――――`,
1441
1443
  `"""`,
@@ -1506,7 +1508,7 @@ function save_files({ tests_path, artifacts_path, file_strings }) {
1506
1508
 
1507
1509
  let count = 1;
1508
1510
  for ( let file_str of file_strings ) {
1509
- let filename = `${ count }_${ Date.now() }.feature`;
1511
+ let filename = `_alkiln_generated_${ count }_${ Date.now() }.feature`;
1510
1512
  count++;
1511
1513
  // Implementation note: If the files don't exist, this creates them
1512
1514
  fs.appendFileSync( `${ tests_path }/${ filename }`, file_str );
@@ -73,7 +73,7 @@ session_vars.get_setup_timeout_ms = function () {
73
73
  return timeout;
74
74
  };
75
75
 
76
- session_vars.get_max_tests_per_generator_scenario = function() {
76
+ session_vars.get_max_tests_per_template_scenario = function() {
77
77
  /** Returns the maximum number of tests to generate for any one generator
78
78
  * Scenario.
79
79
  *
@@ -82,7 +82,7 @@ session_vars.get_max_tests_per_generator_scenario = function() {
82
82
  *
83
83
  * @returns {int} - Max number of tests for one generator Scenario
84
84
  * */
85
- return process.env.MAX_RANDOM_TESTS_PER_SCENARIO || 40;
85
+ return process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO || 40;
86
86
  }
87
87
 
88
88
  session_vars.get_da_server_url = function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "5.13.3-feat-random-3",
3
+ "version": "5.13.3-feat-random-4",
4
4
  "description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -677,10 +677,10 @@ fixts.warnings.no_number.expected =
677
677
  Feature: I generate constrained random tests (generated by ALKiln)
678
678
 
679
679
  @alkiln_extra_intro @alkiln_generator_warning
680
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
680
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
681
681
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
682
682
  """
683
- ――――― Generator file warnings ―――――
683
+ ――――― Template file warnings ―――――
684
684
  🔎 ALK0239 ${ fixts.WARNING_PLACEHOLDER }
685
685
  ―――――
686
686
  """
@@ -713,10 +713,10 @@ fixts.warnings.multiple_numbers.expected =
713
713
  Feature: I generate constrained random tests (generated by ALKiln)
714
714
 
715
715
  @alkiln_extra_intro @alkiln_generator_warning
716
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
716
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
717
717
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
718
718
  """
719
- ――――― Generator file warnings ―――――
719
+ ――――― Template file warnings ―――――
720
720
  🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
721
721
  ―――――
722
722
  """
@@ -750,10 +750,10 @@ fixts.warnings.multiple_number_Steps.expected =
750
750
  Feature: I generate constrained random tests (generated by ALKiln)
751
751
 
752
752
  @alkiln_extra_intro @alkiln_generator_warning
753
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
753
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
754
754
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
755
755
  """
756
- ――――― Generator file warnings ―――――
756
+ ――――― Template file warnings ―――――
757
757
  🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
758
758
  ―――――
759
759
  """
@@ -787,10 +787,10 @@ fixts.warnings.multiple_number_Steps_and_numbers.expected =
787
787
  Feature: I generate constrained random tests (generated by ALKiln)
788
788
 
789
789
  @alkiln_extra_intro @alkiln_generator_warning
790
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
790
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
791
791
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
792
792
  """
793
- ――――― Generator file warnings ―――――
793
+ ――――― Template file warnings ―――――
794
794
  🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
795
795
  🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
796
796
  🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
@@ -840,10 +840,10 @@ Feature: I generate valid constrained random answers tests 1 (generated by ALKil
840
840
  # The 1st of 2 related tests. This 1st one tests uniqueness within one Scenario.
841
841
 
842
842
  @alkiln_extra_intro @alkiln_generator_warning
843
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
843
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
844
844
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
845
845
  """
846
- ――――― Generator file warnings ―――――
846
+ ――――― Template file warnings ―――――
847
847
  🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
848
848
  ―――――
849
849
  """
@@ -868,10 +868,10 @@ Feature: I generate valid constrained random answers tests 2 (generated by ALKil
868
868
  # The 2nd of 2 related tests. Because ALKiln will try to only generate unique tests between all the generators, this 2nd one tests uniqueness of tests between generators. Only the body of the Scenario should matter for uniqueness.
869
869
 
870
870
  @alkiln_extra_intro @alkiln_generator_warning
871
- Scenario: ALKiln humbly begs the author's forgiveness. The next tests might be flawed.
871
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
872
872
  Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
873
873
  """
874
- ――――― Generator file warnings ―――――
874
+ ――――― Template file warnings ―――――
875
875
  🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
876
876
  ―――――
877
877
  """
@@ -888,6 +888,43 @@ fixts.warnings.fewer_unique_than_requested.included_log_codes = [
888
888
  ];
889
889
 
890
890
 
891
+ fixts.warnings.over_max = {};
892
+ fixts.warnings.over_max.max_num_allowed = 1;
893
+ fixts.warnings.over_max.arg =
894
+ `Feature: I generate constrained random tests
895
+
896
+ Scenario: I'm warned of asking for more than the max num tests
897
+ Given ALKiln makes 2 constrained random tests
898
+ Given I start the interview at "test_kickout"
899
+ And ALKiln gets to "end" when I pick from:
900
+ | var | possible_values |
901
+ | user_choice | correct;; wrong |`;
902
+ fixts.warnings.over_max.expected =
903
+ `@alkiln @generated @randomized @constraints
904
+ Feature: I generate constrained random tests (generated by ALKiln)
905
+
906
+ @alkiln_extra_intro @alkiln_generator_warning
907
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
908
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
909
+ """
910
+ ――――― Template file warnings ―――――
911
+ 🔎 ALK0241 ${ fixts.WARNING_PLACEHOLDER }
912
+ ―――――
913
+ """
914
+
915
+ @scenario1_of_1
916
+ Scenario: I'm warned of asking for more than the max num tests (1 of 1)
917
+ Given I start the interview at "test_kickout"
918
+ And I get to any of the question ids ["end"] with this data:
919
+ | var | value |
920
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
921
+ fixts.warnings.over_max.exact_log_codes = [
922
+ `ALK0237`, `ALK0241`, `ALK0243`, `ALK0244`,
923
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
924
+ `ALK0261`, `ALK0262`, `ALK0264`,
925
+ ];
926
+
927
+
891
928
  /**
892
929
  * ===========
893
930
  * Silent warnings
@@ -20,7 +20,7 @@ const TABLE_ROW_REGEX = /^(?!(?:.*\| var \| value \|))(.*\| .* \|)/gm;
20
20
  const TABLE_PLACEHOLDER_REGEX = new RegExp(`(${ RANDOM_TABLE_PLACEHOLDER }(\n)?)+`, `g`);
21
21
 
22
22
  const WARNING_PLACEHOLDER = fixtures.WARNING_PLACEHOLDER;
23
- const WARNING_MSG_REGEX = /(ALK\d{4} )(.*\d{4}-\d\d-\d\d \d\d:\d\d:\d\dUTC.*(?:\n.+))/g;
23
+ const WARNING_MSG_REGEX = /(ALK\d{4} )(.*\d{4}-\d\d-\d\d \d\d:\d\d:\d\dUTC.*(?!\n ―)(?:\n)?.+)/g;
24
24
 
25
25
  const FLUB_PLACEHOLDER = fixtures.FLUB_PLACEHOLDER;
26
26
  const FLUB_REGEX = fixtures.FLUB_OPTIONS_REGEX;
@@ -96,6 +96,11 @@ function mutate_globals_with({ testing_vals, do_compare=false }) {
96
96
  // Reset log codes
97
97
  logger.clear_internal_log_records();
98
98
 
99
+ process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO = 40;
100
+ if ( testing_vals.max_num_allowed ) {
101
+ process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO = testing_vals.max_num_allowed;
102
+ }
103
+
99
104
  // Fresh namespace
100
105
  let generator = new TestGenerator();
101
106
  // Mutates `fixture`
@@ -505,6 +510,23 @@ describe(`Constrained random answers parser, when given a valid generator Scenar
505
510
  });
506
511
  });
507
512
 
513
+ describe(`that asks for over max # of tests allowed - 1 -`, function () {
514
+
515
+ before(function () { mutate_globals_with({ testing_vals: fixtures.warnings.over_max }); });
516
+
517
+ let outer = fixtures.warnings.over_max;
518
+ it(`has these exact log codes with warnings: ${ JSON.stringify( outer.exact_log_codes )}`, function () {
519
+ expect( get_log_codes({ logger }) ).to.have.all.members( fixture.exact_log_codes );
520
+ });
521
+
522
+ it(`returns no errors`, function () { expect( errors ).to.have.lengthOf( 0 ); });
523
+
524
+ it(`has max # of tests - 1`, function () {
525
+ expect( comparable_text( new_contents )).to.equal( fixture.expected );
526
+ });
527
+
528
+ });
529
+
508
530
  describe(`that has a blank var value in a generator column`, function () {
509
531
 
510
532
  before(function () { mutate_globals_with({ testing_vals: fixtures.empty_string_value }); });