Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update hashTests function to support the migration of test results across test plan versions using the v2 test format #880

Merged
merged 12 commits into from
Jan 29, 2024
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/runtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
yarn workspace server db-import-tests:test -c ${IMPORT_ARIA_AT_TESTS_COMMIT_1}
yarn workspace server db-import-tests:test -c ${IMPORT_ARIA_AT_TESTS_COMMIT_2}
yarn workspace server db-import-tests:test -c ${IMPORT_ARIA_AT_TESTS_COMMIT_3}
yarn workspace server db-import-tests:test -c ${IMPORT_ARIA_AT_TESTS_COMMIT_4}
yarn workspace server db-populate-sample-data:test
- name: test
run: yarn test
Expand Down
5 changes: 4 additions & 1 deletion client/components/TestQueue/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export const TEST_QUEUE_PAGE_QUERY = gql`
}
updatedAt
}
testPlanReports(isFinal: false) {
testPlanReports(
isFinal: false
testPlanVersionPhases: [DRAFT, CANDIDATE, RECOMMENDED]
) {
id
conflictsLength
runnableTestsLength
Expand Down
6 changes: 4 additions & 2 deletions config/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ ENVIRONMENT=test
ALLOW_FAKE_ROLE=true
IMPORT_CONFIG=../config/test.env

# Older and newer v1 test format tests, respectively
IMPORT_ARIA_AT_TESTS_COMMIT_1=5fe7afd82fe51c185b8661276105190a59d47322
IMPORT_ARIA_AT_TESTS_COMMIT_2=1aa3b74d24d340362e9f511eae33788d55487d12
# Commit before incoming v2 test format changes
IMPORT_ARIA_AT_TESTS_COMMIT_3=836fb2a997f5b2844035b8c934f8fda9833cd5b2
# Older and newer v2 test format tests, respectively
IMPORT_ARIA_AT_TESTS_COMMIT_3=ab77d47ab19db71c635c9bb459ba5c34182e1400
IMPORT_ARIA_AT_TESTS_COMMIT_4=d34eddbb8e751f07bd28d952de15fa7fe5f07353

GITHUB_OAUTH_SERVER=http://localhost:4466
GITHUB_GRAPHQL_SERVER=http://localhost:4466
Expand Down
16 changes: 16 additions & 0 deletions server/migrations/20231219212344-recalculateV2TestHashes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const { regenerateResultsAndRecalculateHashes } = require('./utils');

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface) {
return queryInterface.sequelize.transaction(async transaction => {
await regenerateResultsAndRecalculateHashes(
queryInterface,
transaction,
`WHERE metadata->>'testFormatVersion' = '2'`
);
});
}
};
Original file line number Diff line number Diff line change
@@ -1,199 +1,10 @@
'use strict';

const {
createTestResultId,
createScenarioResultId,
createAssertionResultId
} = require('../services/PopulatedData/locationOfDataId');
const { hashTests } = require('../util/aria');
const { regenerateResultsAndRecalculateHashes } = require('./utils');

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
/**
* Recompute TestPlanVersion.hashedTests
* @param transaction - The Sequelize.Transaction object.
* See {@https://sequelize.org/api/v6/class/src/sequelize.js~sequelize#instance-method-transaction}
* @returns {Promise<void>}
*/
const computeTestPlanVersionHashedTests = async transaction => {
const results = await queryInterface.sequelize.query(
`SELECT COUNT(*) FROM "TestPlanVersion"`,
{ transaction }
);
const [[{ count: testPlanVersionCount }]] = results;

const testPlanVersionBatchSize = 10;
const iterationsNeeded = Math.ceil(
testPlanVersionCount / testPlanVersionBatchSize
);

for (let i = 0; i < iterationsNeeded; i += 1) {
const multipleOf100 = i % testPlanVersionBatchSize === 0;
if (multipleOf100)
// eslint-disable-next-line no-console
console.info(
'Indexing TestPlanVersions',
i * testPlanVersionBatchSize,
'of',
Number(testPlanVersionCount)
);
const currentOffset = i * testPlanVersionBatchSize;

const [testPlanVersions] = await queryInterface.sequelize.query(
`SELECT id, directory, "gitSha", tests, "updatedAt" FROM "TestPlanVersion" ORDER BY id LIMIT ? OFFSET ?`,
{
replacements: [testPlanVersionBatchSize, currentOffset],
transaction
}
);

await Promise.all(
testPlanVersions.map(async testPlanVersion => {
const hashedTests = hashTests(testPlanVersion.tests);

await queryInterface.sequelize.query(
`UPDATE "TestPlanVersion" SET "hashedTests" = ? WHERE id = ?`,
{
replacements: [hashedTests, testPlanVersion.id],
transaction
}
);
})
);
}
};

/**
* Regenerate the testIds, scenarioIds and assertionsIds in TestRun.testResults, for
* TestRuns
* @param transaction - The Sequelize.Transaction object.
* See {@https://sequelize.org/api/v6/class/src/sequelize.js~sequelize#instance-method-transaction}
* @returns {Promise<void>}
*/
const regenerateExistingTestResults = async transaction => {
const testPlanVersions = await queryInterface.sequelize.query(
`SELECT id, tests FROM "TestPlanVersion"`,
{
type: Sequelize.QueryTypes.SELECT,
transaction
}
);

if (testPlanVersions.length) {
const testPlanReports = await queryInterface.sequelize.query(
`select id, "testPlanVersionId"
from "TestPlanReport"
where "testPlanVersionId" in (?)`,
{
replacements: [testPlanVersions.map(e => e.id)],
type: Sequelize.QueryTypes.SELECT,
transaction
}
);

for (const key in testPlanReports) {
const { id: testPlanReportId } = testPlanReports[key];

const testPlanRuns = await queryInterface.sequelize.query(
`select testPlanRun.id, "testPlanReportId", "atId", "testPlanVersionId", "testResults", tests
from "TestPlanRun" testPlanRun
join "TestPlanReport" testPlanReport
on testPlanReport.id = testPlanRun."testPlanReportId"
join "TestPlanVersion" testPlanVersion
on testPlanVersion.id = testPlanReport."testPlanVersionId"
where "testPlanReportId" = ?`,
{
replacements: [testPlanReportId],
type: Sequelize.QueryTypes.SELECT,
transaction
}
);

for (const key in testPlanRuns) {
const {
id: testPlanRunId,
atId,
testResults,
tests
} = testPlanRuns[key];

tests.forEach(test => {
const testId = test.id;

testResults.forEach(testResult => {
if (testResult.testId === testId) {
// Update testResult.id
const testResultId = createTestResultId(
testPlanRunId,
testResult.testId
);
testResult.id = testResultId;

// The sub-arrays should be in the same order
testResult.scenarioResults.forEach(
(eachScenarioResult, scenarioIndex) => {
eachScenarioResult.scenarioId =
test.scenarios.filter(
scenario =>
scenario.atId === atId
)[scenarioIndex].id;

// Update eachScenarioResult.id
const scenarioResultId =
createScenarioResultId(
testResultId,
eachScenarioResult.scenarioId
);
eachScenarioResult.id =
scenarioResultId;

eachScenarioResult.assertionResults.forEach(
(
eachAssertionResult,
assertionIndex
) => {
eachAssertionResult.assertionId =
test.assertions[
assertionIndex
].id;

// Update eachAssertionResult.id
eachAssertionResult.id =
createAssertionResultId(
scenarioResultId,
eachAssertionResult.assertionId
);
}
);
}
);
}
});
});

await queryInterface.sequelize.query(
`update "TestPlanRun"
set "testResults" = ?
where id = ?`,
{
replacements: [
JSON.stringify(testResults),
testPlanRunId
],
transaction
}
);
// eslint-disable-next-line no-console
console.info(
'Fixing testResults for TestPlanRun',
testPlanRunId
);
}
}
}
};

const updateV1TestPlanVersionsToIncludeTestFormatVersion =
async transaction => {
// No testFormatVersion indicates this is v1 TestPlanVersion data
Expand Down Expand Up @@ -254,8 +65,10 @@ module.exports = {
);

// Recalculate the hashes
await computeTestPlanVersionHashedTests(transaction);
await regenerateExistingTestResults(transaction);
await regenerateResultsAndRecalculateHashes(
queryInterface,
transaction
);
});
}
};
Loading
Loading