Tech Plan: Refactor Automation Framework
Tech Plan: Refactor Automation Framework for Maintainability & Multi-Environment Support
Date: 14-Aug-2025
Status: In Progress
Jira Ticket: https://readyedu.atlassian.net/browse/CG-7872
Framework: CodeceptJS with JavaScript
CI Tool: GitHub Actions
🎯 Objective
Refactor the existing CodeceptJS framework to improve maintainability, clarity, and enable running tests across multiple environments (acceptance, test01, prod). This includes cleaning up smoke tests, centralizing reusable steps, organizing locators better, supporting multi-environment configs, and managing user data efficiently.
1. 🧪 Smoke Testing Tags
✅ Why this is needed
Current smoke tests have duplicate scenarios.
Tagging is inconsistent, causing unreliable smoke runs.
A focused smoke suite ensures quick validation of critical flows.
🔧 Action Items
Review existing smoke test
.featurefiles.Remove tests already covered by other feature files. If not covered, move the tests to the correct feature folder
Add
@smoketags only to essential test casesUpdate the CodeceptJS config and CI scripts to run tests filtered by
@smoke.
⚙️ How we’ll do it
Audit smoke tests for duplication or irrelevance.
Tag essential scenarios with
@smoke.Use CodeceptJS’s
--grep @smokeflag to run smoke suite selectively.
📦 Deliverables
Cleaned and updated smoke tests in their respective feature files
Consistent use of
@smoketagsCI pipeline configured to run smoke tests efficiently
📈 What it improves
Faster CI feedback for critical tests
Reduced noise from redundant tests
Clearer test ownership and focus
2. ♻️ Reusable Step Definitions
✅ Why this is needed
Step definitions are duplicated across feature files.
Maintenance becomes error-prone and slow with repeated steps.
🔧 Action Items
Identify commonly used steps (e.g., login, navigation).
Move these into a shared step definition file
common_steps.js.Refactor feature-specific step files to import and reuse these shared steps.
⚙️ How we’ll do it
Extract reusable steps into
common_steps.js.Replace duplicates with imports from this shared file.
Maintain consistent step phrasing for readability.
📦 Deliverables
common_steps.jsfile with common stepsRefactored feature step files
Updated project documentation if needed
📈 What it improves
Easier to maintain step definitions
Consistent test behavior across features
Reduced duplication and cleaner codebase
3. 📍 Centralized Locators (CodeceptJS)
✅ Why this is needed
Locators are scattered and sometimes duplicated.
UI changes require updates in multiple places.
Centralized locators improve maintainability and clarity.
🔧 Action Items
Create a
locators/folder in the project.Organize locator files by feature/module:
commonLocators.jsfor shared UI elementseventsLocators.jsfor Events featuregradesLocators.jsfor Grades featuregroupsLocators.jsfor Groups feature
Export locators using
module.exports = {}.Refactor page objects and steps to
require()locators from these files.
⚙️ How we’ll do it
Folder Structure:
locators/
├── commonLocators.js
├── eventsLocators.js
├── gradesLocators.js
└── groupsLocators.js
Example: eventsLocators.js
Module.exports = {
createEventButton: locate('button').withText('Create Event'),
eventTitleInput: '#event-title',
datePicker: '.datepicker',
};
Example: commonLocators.js
module.exports = {
header: '.main-header',
footer: '.main-footer',
toastMessage: '.toast-message',
modalCloseButton: '.modal-close',
loader: '.spinner',
};
Using locators in a page object or step file:
const { I } = inject();
const eventsLocators = require('../locators/eventsLocators');
const commonLocators = require('../locators/commonLocators');
module.exports = {
createNewEvent() {
I.click(eventsLocators.createEventButton);
I.fillField(eventsLocators.eventTitleInput, 'Test Event');
I.click(commonLocators.modalCloseButton);
}
};
📦 Deliverables
Organized
locators/folder with feature-based locator filesRefactored page objects and step files using these locators
📈 What it improves
Simplifies updates when UI changes
Reduces duplication of selectors
Improves clarity and maintainability of tests
4. 🌐 Multi-Environment Setup (using .env files)
✅ Why this is needed
Each environment (acceptance, test01, prod) requires different URLs, credentials, and config.
Managing these settings in separate
.envfiles keeps them clean and easy to switch.
🔧 Action Items
Create
.envfiles named exactly per environment:acceptance.envtest01.envprod.env
Use the
dotenvpackage to load the correct file dynamically based on theENVvariable.Update framework config and CI to respect the chosen environment.
⚙️ How we’ll do it
Sample code to load the environment:
const dotenv = require('dotenv');const env = process.env.ENV || 'acceptance'; // default environmentdotenv.config({ path: `${env}.env` });Access config values via
process.envin tests and config files.Make sure CI sets the
ENVvariable correctly before running tests.
📦 Deliverables
.envfiles named asacceptance.env,test01.env,prod.envwith environment-specific settingsDynamic
.envloading in test setupUpdated
codecept.conf.jsto useprocess.envvariables
📈 What it improves
Clear separation of environment configs
Easy switching of environments with just one env var change
Avoids hardcoding sensitive info in code
5. 👤 User Data Configuration (via .env files)
✅ Why this is needed
User credentials and test data vary per environment.
Keeping user data in environment-specific
.envfiles aligns test data with environment config.Avoids hardcoding sensitive info in the codebase.
🔧 Action Items
Store user credentials and other environment-specific test data in the same
.envfiles, e.g.:acceptance.envtest01.envprod.env
Refactor user data helper module to read from
process.env.Update step definitions and tests to use this centralized user data source.
⚙️ How we’ll do it
Sample variables in
acceptance.env:
TEST_ENV=acceptance
BASE_URL=https://qa.campusgroups.com
HEADLESS=true
ADMIN_EMAIL=admin_email
ADMIN_PASSWORD=acceptPass123
TEST_USER_EMAIL=testuser_email
TEST_USER_PASSWORD=testPass123
Example userData.js helper module:
module.exports = {
admin: {
username: process.env.ADMIN_EMAIL,
password: process.env.ADMIN_PASSWORD,
},
user: {
username: process.env.TEST_USER_EMAIL,
password: process.env.TEST_USER_PASSWORD,
}
};
In tests or step files, require userData.js and use the properties for login and other operations.
📦 Deliverables
User credentials and test data in environment-specific
.envfiles (acceptance.env, etc.)userData.jsmodule reading fromprocess.envTests refactored to consume centralized user data
📈 What it improves
Environment-specific test data management
Enhanced security by not hardcoding sensitive data
Easier updates and consistency across environments
📁 Final Proposed Folder Structure
.
├── locators/
│ ├── commonLocators.js
│ ├── eventsLocators.js
│ ├── gradesLocators.js
│ └── groupsLocators.js
├── steps/
│ ├── common_steps.js
│ └── [feature]_steps.js
├── env/
│ ├── env.acceptance.js
│ ├── env.test01.js
│ └── env.prod.js
├── data/
│ └── userData.js
├── pages/
│ └── [pageObjects].js
├── features/
│ └──smokeTests/
│ └── smoke.feature
└── codecept.conf.js
✅ Testing Strategy
Run full regression locally after each refactor step.
Validate smoke tests run correctly with
--grep @smoke.Test all environments by switching
ENVvariables and confirming tests run successfully.Review logs and reports for consistent test behavior.
📌 Final Notes
Align smoke tests with product feature areas and corresponding feature folders. Create or reorganize feature folders as needed for better coverage and clarity.
Reference: https://readyedu.atlassian.net/wiki/spaces/PROD/pages/505249797All changes will be pushed in small, reviewable PRs.
Backward compatibility will be maintained.
README and Confluence will be updated with new folder and config structures.