Test Management for Jira Server

Migration Scripts

When migrating complex sets of data from a different test management tool or Excel document, Test Management for Jira’s self-service import options may not meet your specific needs. In this event, we have a REST API with an extensive list of endpoints for tasks such as creating new test results and retrieving test cases. This allows you to seamlessly import your data into Test Management for Jira by pulling data from a file source, making any relevant changes, and then using the API to push the data to Test Management for Jira.

The following sections present sample migration scripts that use Test Management for Jira’s REST API:

Migrate Test Cases with Custom Fields

This script takes a list of test cases with custom fields and creates new test cases in Test Management for Jira that include the custom fields.

Custom fields must be created in Test Management for Jira prior to running the migration script.
// Migrate test cases with custom fields

const fetch = require('node-fetch');

class TestCaseMigrator {
constructor(jiraSettings, testCasesToMigrate) {
this._jiraSettings = jiraSettings;
this._testCasesToMigrate = testCasesToMigrate;
this._authString = 'Basic ' + Buffer.from(this._jiraSettings.user + ':' + this._jiraSettings.password).toString('base64');
}

    async migrateTestCases() {
        for(let testCase of this._testCasesToMigrate) {
            await this._createTestCase(testCase);
        }
    }

    async _createTestCase(testCase) {
        const request = this._buildRequest(testCase);
        const url = encodeURI(this._jiraSettings.url + '/rest/atm/1.0/testcase');
        const response = await fetch(url, request);
        if(response.status !== 201) throw 'Error creating test case: ' + testCase.name;
        const jsonResponse = await response.json();
        console.log('Test case created: ' + jsonResponse.key + ' - ' + testCase.name);
    }

    _buildRequest(body) {
        return {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': this._authString
            }
        };
    }
}

async function run() {
/ Your settings
const settings = {
'url': '<<your-jira-url>>',
'user': '<<your-user>>',
'password': '<<your-password>>'
};
const projectKey = '<<A project key e.g. PROJ>>';

    // These test cases could have been read from any source
    // and transformed to have this exact format. Custom fields
    // need to exist prior to running this script
    const testCasesToMigrate = [{
        'projectKey': projectKey,
        'name': 'First test case',
        'folder': '/Import from legacy system',
        'customFields': {
            'A checkbox custom field': true,
            'A number custom field': 12,
            'A text custom field': 'Some text here'
        }
    }, {
        'projectKey': projectKey,
        'name': 'Another test case',
        'folder': '/Import from legacy system',
        'customFields': {
            'A user custom field': 'my.user.key',
            'A decimal number custom field': 1.2,
            'A select list custom field': 'This is the option label'
        }
    }];

    await new TestCaseMigrator(settings, testCasesToMigrate).migrateTestCases();
}

run();

Migrate Test Cases with Attachments

This script takes a list of test cases with attachments and creates new test cases in Test Management for Jira with the attachments included.

// Migrate test cases with attachment

const fetch = require('node-fetch');
const fs = require('fs');
const FormData = require('form-data');

class TestCaseMigrator {
constructor(jiraSettings, testCasesToMigrate) {
this._jiraSettings = jiraSettings;
this._testCasesToMigrate = testCasesToMigrate;
this._authString = 'Basic ' + Buffer.from(this._jiraSettings.user + ':' + this._jiraSettings.password).toString('base64');
}

async migrateTestCases() {
        for(let testCase of this._testCasesToMigrate) {
            const filePath = testCase.attachment;
            delete(testCase.attachment);
            const testCaseKey = await this._createTestCase(testCase);
            await this._uploadAttachment(testCaseKey, filePath);
        }
    }

    async _createTestCase(testCase) {
        const request = this._buildRequest(testCase);
        const url = encodeURI(this._jiraSettings.url + '/rest/atm/1.0/testcase');
        const response = await fetch(url, request);
        const jsonResponse = await response.json();
        if(response.status !== 201) throw 'Error creating test case: ' + testCase.name;
        console.log('Test case created: ' + jsonResponse.key + ' - ' + testCase.name);
        return jsonResponse.key;
    }

    async _uploadAttachment(testCaseKey, filePath) {
        const formData = new FormData();
        formData.append('file', fs.createReadStream(filePath));

        const request = {
            method: 'POST',
            body: formData,
            headers: formData.getHeaders()
        };
        request.headers.Authorization = this._authString;

        const url = encodeURI(this._jiraSettings.url + '/rest/atm/1.0/testcase/' + testCaseKey + '/attachments');
        const response = await fetch(url, request);
        if(response.status !== 201) throw 'Error uploading attachment ' + filePath + ' to test case ' + testCaseKey;
        console.log('Attachment uploaded: ' + testCaseKey + ' - ' + filePath);
    }

    _buildRequest(body) {
        return {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': this._authString
            }
        };
    }
}

async function run() {
/ Your settings
const settings = {
'url': '<<your-jira-url>>',
'user': '<<your-user>>',
'password': '<<your-password>>'
};
const projectKey = '<<A project key e.g. PROJ>>';

    // These test cases could have been read from any source
    // and transformed to have this exact format.
    const testCasesToMigrate = [{
        'projectKey': projectKey,
        'name': 'Test case with attachment',
        'attachment': './aDocument.pdf'
    }, {
        'projectKey': projectKey,
        'name': 'Another test case with attachment',
        'attachment': './anImage.png'
    }];

    await new TestCaseMigrator(settings, testCasesToMigrate).migrateTestCases();
}

run();

Migrate Test-Execution Results

This script takes a list of test cases and creates a new test case in Test Management for Jira for each one, prior to creating any executions related to any test case.

// Migrate test cases with test executions

const fetch = require('node-fetch');

class TestCaseMigrator {
constructor(jiraSettings, testCasesToMigrate) {
this._jiraSettings = jiraSettings;
this._testCasesToMigrate = testCasesToMigrate;
this._authString = 'Basic ' + Buffer.from(this._jiraSettings.user + ':' + this._jiraSettings.password).toString('base64');
}

    async migrateTestCases() {
        for(let testCase of this._testCasesToMigrate) {
            await this._createTestCase(testCase);
        }
    }

    async _createTestCase(testCase) {
        const executions = testCase.executions;
        delete(testCase.executions);
        const request = this._buildRequest(testCase);
        const url = encodeURI(this._jiraSettings.url + '/rest/atm/1.0/testcase');
        const response = await fetch(url, request);
        if(response.status !== 201) throw 'Error creating test case: ' + testCase.name;
        const jsonResponse = await response.json();
        console.log('Test case created: ' + jsonResponse.key + ' - ' + testCase.name);
        await this._createTestExecutions(testCase.projectKey, jsonResponse.key, executions);
    }

    async _createTestExecutions(projectKey, testCaseKey, executions) {
        for(let execution of executions) {
            execution.projectKey = projectKey;
            execution.testCaseKey = testCaseKey;
            const request = this._buildRequest(execution);
            const url = encodeURI(this._jiraSettings.url + '/rest/atm/1.0/testresult');
            const response = await fetch(url, request);
            if(response.status !== 201) throw 'Error creating test execution: ' + testCaseKey;
            console.log('Test execution created: ' + testCaseKey);
        }
    }

    _buildRequest(body) {
        return {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': this._authString
            }
        };
    }
}

async function run() {
/ Your settings
const settings = {
'url': '<<your-jira-url>>',
'user': '<<your-user>>',
'password': '<<your-password>>'
};
const projectKey = '<<A project key e.g. PROJ>>';

    // These test cases could have been read from any source
    // and transformed to have this exact format.
    const testCasesToMigrate = [{
        'projectKey': projectKey,
        'name': 'Test case with executions',
        'executions': [{
            'status': 'Pass',
            'environment': 'Firefox',
            'executionTime': 180000,
            'executionDate': '2018-12-13T15:22:00-0300',
        }, {
            'status': 'Fail',
            'environment': 'Chrome',
            'executionTime': 365000,
            'executionDate': '2018-12-13T18:11:00-0300',
        }]
    }, {
        'projectKey': projectKey,
        'name': 'Test case with simpler executions',
        'executions': [{
            'status': 'Pass'
        }, {
            'status': 'Fail'
        }]
    }];

    await new TestCaseMigrator(settings, testCasesToMigrate).migrateTestCases();
}

run();