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

need to run specific test specs on respective thread. #177

Open
mukeshnagpal90 opened this issue Nov 16, 2023 · 5 comments
Open

need to run specific test specs on respective thread. #177

mukeshnagpal90 opened this issue Nov 16, 2023 · 5 comments

Comments

@mukeshnagpal90
Copy link

I have two folders containing spec files:
folder1 having specs with user1
folder2 having specs with user2
i want to run these specs on two threads where thread1 run folder1 specs i.e. user1 specs and thread2 specs should run on thread2.

Please suggest and provide me solution.

@mukeshnagpal90
Copy link
Author

Hi Team,

can anyone help me with the above task?

@mukeshnagpal90
Copy link
Author

Hi Team,

Please help me in resolving the above issue.

@ketteq-neon
Copy link

Hi Team,

Please have a look into the query.

@khaja38
Copy link

khaja38 commented Dec 7, 2023

Hey hi, if you goto node_module/cypress-parallel/test-suites.js you will find a method/function distributeTestsByWeight(testSuitePaths) which will guide you.

  1. It will sort the weights json as per weights in descending order
  2. Then it will initiate the threads object array with the size we've mentioned in the cmd
  3. Later, it will assign the threads with the spec with highest weight
  4. if threads are filled, it will sort the threads in ascending order according to total weight assigned to thread, now it will repeat the step 3, 4 iteratively.

For eg, if you have 7 specs with weights 14, 12, 10, 8, 6, 4, 2 and threads = 4

t1 = [14], t2 = [12], t3 =[10], t4 = [8]
in later stages...
t1 = [8, 6], t2 = [10], t3 =[12], t4=[14]
t1 = [10, 4], t2 = [8, 6], t3=[12], t4=[14]
t1=[12, 2], t2=[10, 4], t3=[8, 6], t4=[14]
The above will be the final thread list format.

So, play with it a bit, you will be able to understand.

@MosesWescombe
Copy link

I had the same issue. I made a node.js script that will combine tests in folders into files. I never managed to get the tests to pass when running in parallel due to complex state management, but running it this way did manage to get the folders to act like 'threads'.

My scripts looked like:

"combine": "rm -rf ./cypress/e2e/execution && node cypress/combine-threads.js",
"cy:parallel": "yarn run combine && cypress-parallel -s cypress:run:chrome -t 4 -m false -n ../../node_modules/cypress-multi-reporters -d './cypress/e2e/execution' -a '\"--config baseUrl=... --env REACT_API_URL=..."' && rm -rf ./cypress/e2e/execution"

Where -d is defining where my .cy.ts files are. The script compiles them into this location. Just make sure all of the contents of each test file are contained within describe() as the files are simply pasted together.

var path = require('path');

var e2eDir = './cypress/e2e';
var executionDir = './cypress/e2e/execution';

// Helper function to adjust import paths
function adjustImportPaths(content, originalDirPath) {
    const importRegex = /^import\s+{([^}]+)}\s+from\s+['"](.+?)['"];$/gm;
    const importsMap = new Map();

    content = content.replace(importRegex, (match, imports, from) => {
        // Check if the import is from a package or a local file
        const isPackageImport = from.startsWith('.') ? false : true;

        let normalizedFrom = from;
        if (!isPackageImport) {
            // It's a local import, adjust the path
            normalizedFrom = path.relative(executionDir, path.resolve(originalDirPath, from)).replace(/\\/g, '/');
        }

        const importItems = imports
            .split(',')
            .map((item) => item.trim())
            .filter((item) => item);

        if (importsMap.has(normalizedFrom)) {
            const existingImports = importsMap.get(normalizedFrom);
            importItems.forEach((item) => {
                if (!existingImports.includes(item)) {
                    existingImports.push(item);
                }
            });
        } else {
            importsMap.set(normalizedFrom, importItems);
        }

        return ''; // Remove the original import statement
    });

    // Reconstruct combined import statements at the beginning of the content
    const combinedImports = Array.from(
        importsMap,
        ([from, imports]) => `import { ${imports.join(', ')} } from '${from}';`
    ).join('\n');
    return combinedImports + '\n' + content;
}

// Function to combine files from a single directory
function combineFilesFromDirectory(dirPath, targetFileName) {
    let combinedContent = '';
    const importStatements = new Set();
    const files = fs.readdirSync(dirPath);

    files.forEach((file) => {
        const filePath = path.join(dirPath, file);
        const stat = fs.statSync(filePath);

        if (stat.isFile() && filePath.endsWith('.cy.ts')) {
            let content = fs.readFileSync(filePath, 'utf8');

            // Adjust the import paths in the content
            content = adjustImportPaths(content, dirPath);

            // Extract and remove import statements from content
            content = content.replace(/^import .+ from .+;$/gm, (importStatement) => {
                importStatements.add(importStatement);
                return '';
            });

            combinedContent += `\n${content}`;
        }
    });

    // Prepend combined import statements to the top
    combinedContent = Array.from(importStatements).join('\n') + combinedContent;

    if (!fs.existsSync(executionDir)) {
        fs.mkdirSync(executionDir, { recursive: true });
    }

    fs.writeFileSync(path.join(executionDir, targetFileName), combinedContent);
}

// Function to iterate through each subdirectory of e2e and combine files
function processDirectories(parentDirectory) {
    const directories = fs
        .readdirSync(parentDirectory, { withFileTypes: true })
        .filter((dirent) => dirent.isDirectory())
        .map((dirent) => dirent.name);

    directories.forEach((dir) => {
        const dirPath = path.join(parentDirectory, dir);
        const targetFileName = `${dir}.cy.ts`;
        combineFilesFromDirectory(dirPath, targetFileName);
        console.log(`Combined file created for ${dirPath}: ${targetFileName}`);
    });
}

processDirectories(e2eDir);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants