Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/end2end.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ jobs:
- name: Check for unused step definitions
working-directory: tests/functional
run: yarn unused-steps
- name: Check that all scenarios have a version tag
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we want that?

this "tagging" was introduced when CTST was used in Artesca, and embedded the tests : so there was one version of CTST and tests targeting multiple zenko versions.

the tests are now managed in git -so the information is really available via git blame or others-, I don't see the benefit of manually adding the tag on every test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yes, there is another version of this pr where I just remove all tags + the useless before hook
I kinda liked having directly visible tags attached to the scenarios as its faster to read than commits but you're right

working-directory: tests/functional
run: yarn ensure-version-tags

end2end-pra:
needs: [build-kafka, build-mongodb]
Expand Down
1 change: 0 additions & 1 deletion tests/functional/ctst/common/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import 'cli-testing/hooks/KeycloakSetup';
import 'cli-testing/hooks/Logger';
import 'cli-testing/hooks/versionTags';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrote why im doing this in the top comment of the pr


// HTTPS should not cause any error for CTST
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
Expand All @@ -43,7 +42,7 @@

setParallelCanAssign(noParallelRun);

BeforeAll(async function () {

Check warning on line 45 in tests/functional/ctst/common/hooks.ts

View workflow job for this annotation

GitHub Actions / lint-functional-tests

Unexpected function expression
const kafkaHosts = process.env['KAFKA_HOST_PORT'];
const dlqTopic = process.env['KAFKA_DEAD_LETTER_TOPIC'];
if (kafkaHosts && dlqTopic) {
Expand All @@ -51,7 +50,7 @@
}
});

AfterAll(async function () {

Check warning on line 53 in tests/functional/ctst/common/hooks.ts

View workflow job for this annotation

GitHub Actions / lint-functional-tests

Unexpected function expression
await stopDLQConsumer();
});

Expand Down
75 changes: 75 additions & 0 deletions tests/functional/ctst/scripts/ensureVersionTags.ts
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no tests were breaking this rule, but wanna enforce it, it's important to know "this test was shipped with a feature on version 2.15.1"

Tested it in codespace by removing tags from some scenarios :

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually put them in .github/scripts ? Also we should have tests for it 🙏

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Verifies that every Scenario in the ctst feature files
* has a semver version tag (e.g. @2.6.0), either on the Feature,
* an enclosing Rule, or directly on the scenario.
*
* Exits with code 1 and lists offenders if any are missing.
*/

/* eslint-disable no-console */

import { Parser, AstBuilder, GherkinClassicTokenMatcher } from '@cucumber/gherkin';
Comment thread
SylvainSenechal marked this conversation as resolved.
import { IdGenerator } from '@cucumber/messages';
import * as fs from 'fs';
import * as path from 'path';

const VERSION_TAG_REGEX = /^@\d+\.\d+\.\d+$/;
const FEATURES_DIR = path.resolve(__dirname, '../features');

function collectFeatureFiles(dir: string): string[] {
const files: string[] = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...collectFeatureFiles(full));
} else if (entry.name.endsWith('.feature')) {
files.push(full);
}
}
return files;
}

let totalScenarios = 0;
const offenders: string[] = [];
const parser = new Parser(new AstBuilder(IdGenerator.incrementing()), new GherkinClassicTokenMatcher());

for (const file of collectFeatureFiles(FEATURES_DIR)) {
const rel = path.relative(FEATURES_DIR, file);
const ast = parser.parse(fs.readFileSync(file, 'utf8'));
const feature = ast.feature;
if (!feature) { continue; }

const featureHasVersion = feature.tags.some(t => VERSION_TAG_REGEX.test(t.name));

for (const child of feature.children) {
if (child.scenario) {
totalScenarios++;
const hasVersion = featureHasVersion || child.scenario.tags.some(t => VERSION_TAG_REGEX.test(t.name));
if (!hasVersion) {
offenders.push(` ${rel}:${child.scenario.location.line} — "${child.scenario.name}"`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this is needed ?

}
} else if (child.rule) {
// Version tag can be inherited from Feature or Rule
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Version tag can be inherited from Feature or Rule

const ruleHasVersion = child.rule.tags.some(t => VERSION_TAG_REGEX.test(t.name));
for (const ruleChild of child.rule.children) {
if (!ruleChild.scenario) { continue; } // skip Background inside Rule
totalScenarios++;
const hasVersion = featureHasVersion || ruleHasVersion
|| ruleChild.scenario.tags.some(t => VERSION_TAG_REGEX.test(t.name));
if (!hasVersion) {
offenders.push(` ${rel}:${ruleChild.scenario.location.line} — "${ruleChild.scenario.name}"`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create a new function to do that instead of duplicating the logic (ruleChild vs child).

}
}
}
// Background nodes are intentionally ignored
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have twice the same comment https://github.com/scality/Zenko/pull/2421/changes#diff-637785e467dea30f38c5f19d551eefd93a7feffae2da263d44066c7d8c8c2adcR55. It's maybe better to add the why, than just describing the code (if relevant).

}
}

if (offenders.length > 0) {
console.error(`\n${offenders.length} scenario(s) missing a version tag (@X.Y.Z):\n`);
offenders.forEach(o => console.error(o));
console.error('\nAdd a version tag (e.g. @2.15.0) to each scenario or its parent Feature.\n');
process.exit(1);
}

console.log(`All ${totalScenarios} scenarios have a version tag.`);
5 changes: 4 additions & 1 deletion tests/functional/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"node": ">=24"
},
"dependencies": {
"@cucumber/cucumber": "^12.7.0",
"@cucumber/cucumber": "^12.9.0",
Copy link
Copy Markdown
Contributor Author

@SylvainSenechal SylvainSenechal May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kinda useless because of the caret but still did it as im adding the dev dependencies

"@kubernetes/client-node": "^1.4.0",
"@platformatic/kafka": "^1.30.0",
"@smithy/node-http-handler": "^4.0.0",
Expand All @@ -33,6 +33,8 @@
"@aws-sdk/client-iam": "^3.901.0",
"@aws-sdk/client-s3": "^3.931.0",
"@aws-sdk/client-sts": "^3.901.0",
"@cucumber/gherkin": "^38.0.0",
"@cucumber/messages": "^32.3.1",
"@eslint/compat": "^1.1.1",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.9.1",
Expand All @@ -50,6 +52,7 @@
"scripts": {
"build:cucumber": "tsc --build tsconfig.json",
"unused-steps": "! yarn cucumber-js --config ctst/cucumber.config.cjs --dry-run --format usage 2>&1 | grep UNUSED",
"ensure-version-tags": "ts-node ctst/scripts/ensureVersionTags.ts",
"test:aws_crr": "mocha --config mocha/.mocharc.js -t 10000 --reporter-options configFile=mocha/mocha-reporter.json,cmrOutput=mocha-junit-reporter+testsuitesTitle+test_aws_crr mocha/backbeat/tests/crr/awsBackend.js",
"test:azure_crr": "mocha --config mocha/.mocharc.js -t 10000 --reporter-options configFile=mocha/mocha-reporter.json,cmrOutput=mocha-junit-reporter+testsuitesTitle+test_azure_crr mocha/backbeat/tests/crr/azureBackend.js",
"test:gcp_crr": "mocha --config mocha/.mocharc.js -t 10000 --reporter-options configFile=mocha/mocha-reporter.json,cmrOutput=mocha-junit-reporter+testsuitesTitle+test_gcp_crr mocha/backbeat/tests/crr/gcpBackend.js",
Expand Down
30 changes: 11 additions & 19 deletions tests/functional/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -871,20 +871,20 @@
dependencies:
regexp-match-indices "1.0.2"

"@cucumber/cucumber@^12.7.0":
version "12.8.1"
resolved "https://registry.yarnpkg.com/@cucumber/cucumber/-/cucumber-12.8.1.tgz#7873a1f7f60141d6077755bbbdc819e739fa6d4a"
integrity sha512-hCXxiStjbZsRVZlV+CMywkqBtJ6RZTQeXSBZGPHm1YoIOI6YB8pCo0KlnJMmxfKfoeUKagtQMNPnpJBXwhkUjQ==
"@cucumber/cucumber@^12.9.0":
version "12.9.0"
resolved "https://registry.yarnpkg.com/@cucumber/cucumber/-/cucumber-12.9.0.tgz#23ec33efd561e34a4355320cb8abc8ec41824ea0"
integrity sha512-QbgEo/DcKFMRGL+yULh8Kw6peEfdPJjhYjpKp0dYc+6Dv1Bmp6hvxIdTi2CIinYBCXhvCZzNO1Ct/n6Dk1yAtA==
dependencies:
"@cucumber/ci-environment" "13.0.0"
"@cucumber/cucumber-expressions" "19.0.0"
"@cucumber/gherkin" "38.0.0"
"@cucumber/gherkin-streams" "6.0.0"
"@cucumber/gherkin-utils" "11.0.0"
"@cucumber/html-formatter" "23.0.0"
"@cucumber/html-formatter" "23.1.0"
"@cucumber/junit-xml-formatter" "0.13.3"
"@cucumber/message-streams" "4.1.1"
"@cucumber/messages" "32.2.0"
"@cucumber/messages" "32.3.1"
"@cucumber/pretty-formatter" "1.0.1"
"@cucumber/tag-expressions" "9.1.0"
assertion-error-formatter "^3.0.0"
Expand Down Expand Up @@ -942,10 +942,10 @@
dependencies:
"@cucumber/messages" ">=31.0.0 <33"

"@cucumber/html-formatter@23.0.0":
version "23.0.0"
resolved "https://registry.yarnpkg.com/@cucumber/html-formatter/-/html-formatter-23.0.0.tgz#066f548f55274b58b67b4930836bd73579a9bf07"
integrity sha512-WwcRzdM8Ixy4e53j+Frm3fKM5rNuIyWUfy4HajEN+Xk/YcjA6yW0ACGTFDReB++VDZz/iUtwYdTlPRY36NbqJg==
"@cucumber/html-formatter@23.1.0":
version "23.1.0"
resolved "https://registry.yarnpkg.com/@cucumber/html-formatter/-/html-formatter-23.1.0.tgz#6b9f759f9d50355b0cb28edde3ad3580d91f7081"
integrity sha512-DcCSFoGs6jbwzXPgX1CwgJKEE+ZMcIEzq/0Memg0o24maNn9NJizBFHmoFWG4iv/OxHza+mvc+56cTHetfHndw==

"@cucumber/junit-xml-formatter@0.13.3":
version "0.13.3"
Expand All @@ -964,15 +964,7 @@
dependencies:
mime "^3.0.0"

"@cucumber/messages@32.2.0":
version "32.2.0"
resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-32.2.0.tgz#a6cff1646366af60e0202e934d6f43f8ccce877f"
integrity sha512-oYp1dgL2TByYWL51Z+rNm+/mFtJhiPU9WS03goes9EALb8d9GFcXRbG1JluFLFaChF1YDqIzLac0kkC3tv1DjQ==
dependencies:
class-transformer "0.5.1"
reflect-metadata "0.2.2"

"@cucumber/messages@>=31.0.0 <33", "@cucumber/messages@^32.0.0":
"@cucumber/messages@32.3.1", "@cucumber/messages@>=31.0.0 <33", "@cucumber/messages@^32.0.0", "@cucumber/messages@^32.3.1":
version "32.3.1"
resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-32.3.1.tgz#8c6990554c35fb9bcff0b7f09fe52ddfd479dbce"
integrity sha512-yNQq1KoXRYaEKrWMFmpUQX7TdeQuU9jeGgJAZ3dArTsC/T4NpJ6DnqaJIIgwPnz/wtQIQTNX7/h0rOuF5xY4qQ==
Expand Down
Loading