Sharing an Object Map across test suites

Last edited on

Introduction

It can sometimes be useful to have two or more test suites share the same Object Map. By default, test suites store their Object Map in the objects.map file which is kept in the same directory as the test suite's suite.conf file which holds the test suite's settings. However, you can change the objects.map file that the test suite uses, either through the Squish IDE or by directly editing the suite.conf file.

Sharing an Object Map using the Squish IDE's Settings

Click the Test Suites view's Test Suite Settings toolbar button to make the Test Suite Settings view visible. Scroll down until you can see the Object Map section.

Replace the objects.map with the name of the Object Map file you want to use (including its full path).

It may prove worthwhile to create an environment variable that holds the shared path (as the screenshot above illustrates).

Another alternative is to create a symbolic link to the shared objects.map file in the folder of every test suite that you want to use it. (Note that on Windows symbolic links are only supported by NTFS file systems.)

Sharing an Object Map by Editing the suite.conf File

Every test suite has a suite.conf file which stores suite-specific global settings. Each setting appears on its own line and has the format key_=_value. By default, test suites use the objects.map file that is in the same directory as the suite.conf file, but this can be overridden by modifying the OBJECTMAP entry. For example, the default entry should look like this:

OBJECTMAP=objects.map

If the shared objects.map file should be C:\MyApp\Testing\objects.map, change this as follows:

OBJECTMAP=C:\MyApp\Testing\objects.map

Change this entry in every test suite's suite.conf file that you want to share the same Object Map.

Merging Object Maps

JavaScript

function main()
{
    var om1 = squishinfo.testCase + "/../objects.map";
    var om2 = "C:/Users/myuser/suite_SecondSuite/objects.map";
    var om_merged = squishinfo.testCase + "/../objects_merged.map";

    // Merge objects maps:
    merge_object_maps(om1, om2, om_merged);

    // Load merged object map:
    objectMap.load(om_merged);

    // Output symbolic names of merged object
    // map:
    var sns = objectMap.symbolicNames();
    for (var i = 0; i < sns.length; i++) {
        var sn = sns[i];
        test.log("Symbolic name: " + sn);
    }
}

function merge_object_maps(object_map_file_name1, object_map_file_name2, merged_object_map_file_name)
{
    var is_in = function(str, str_array) {
            for (var i = 0; i < str_array.length; i++) {
            if (str == str_array[i]) {
                return true;
            }
        }
        return false;
    };

    objectMap.load(object_map_file_name1);
    var symbolic_names1 = objectMap.symbolicNames();

    objectMap.load(object_map_file_name2)
    var symbolic_names2 = objectMap.symbolicNames();

    var new_object_map_str = "";

    // Add object names that are unique to first
    // object map:
    objectMap.load(object_map_file_name1);
    for (var i = 0; i < symbolic_names1.length; i++) {
        var sn = symbolic_names1[i];
        if (!is_in(sn, symbolic_names2)) {
            var rn = objectMap.realName(sn);
            new_object_map_str += sn + "\t" + rn + "\n";
        }
    }

    // Add object names that are unique to second
    // object map:
    objectMap.load(object_map_file_name2)
    for (var i = 0; i < symbolic_names2.length; i++) {
        var sn = symbolic_names2[i];
        if (!is_in(sn, symbolic_names1)) {
            var rn = objectMap.realName(sn);
            new_object_map_str += sn + "\t" + rn + "\n";
        }
    }

    // Add object names that appear in both object
    // maps:
    objectMap.load(object_map_file_name1)
    for (var i = 0; i < symbolic_names1.length; i++) {
        var sn = symbolic_names1[i];
        if (is_in(sn, symbolic_names2)) {
            test.warning("Duplicate symbolic name found: " + sn);

            // Add object name of first object map:
            var rn = objectMap.realName(sn);
            new_object_map_str += sn + "\t" + rn + "\n";

            // Add object name of second object map:
            objectMap.load(object_map_file_name2);
            rn = objectMap.realName(sn);
            new_object_map_str += sn + "\t" + rn + "\n";
            objectMap.load(object_map_file_name1);
        }
    }

    file = File.open(merged_object_map_file_name, "w");
    file.write(new_object_map_str.replace(/\\/g, "\\\\"));
    file.close();
}
test.js

Python

import codecs

def main():
    om1 = squishinfo.testCase + "/../objects.map"
    om2 = "C:/Users/myuser/suite_SecondSuite/objects.map"
    om_merged = squishinfo.testCase + "/../objects_merged.map"

    # Merge objects maps:
    merge_object_maps(om1, om2, om_merged)

    # Load merged object map:
    objectMap.load(om_merged)

    # Output symbolic names of merged object
    # map:
    for sn in objectMap.symbolicNames():
        test.log("Symbolic name: " + sn)

def merge_object_maps(object_map_file_name1, object_map_file_name2, merged_object_map_file_name):
    names1 = {}
    objectMap.load(object_map_file_name1)
    for sn in objectMap.symbolicNames():
        names1[sn] = objectMap.realName(sn)

    names2 = {}
    objectMap.load(object_map_file_name2)
    for sn in objectMap.symbolicNames():
        names2[sn] = objectMap.realName(sn)

    new_names = {}

    # Add object names that are unique to first
    # object map:
    for sn in names1.iterkeys():
        if sn not in names2:
            new_names[sn] = names1[sn]

    # Add object names that are unique to second
    # object map:
    for sn in names2.iterkeys():
        if sn not in names1:
            new_names[sn] = names2[sn]

    # Add object names that appear in both object
    # maps but have different real names:
    for sn in names1.iterkeys():
        if sn not in names2:
            continue

        # If the real names are identical, add:
        if names1[sn] == names2[sn]:
            test.log('Both objects.maps contain symbolic name %s with same real name: %s' % (sn, names1[sn]))
            new_names[sn] = names1[sn]
            continue

        test.warning('Duplicate symbolic name with different real names found: %s' % sn)
        test.warning('Real name from object map #1: %s' % names1[sn])
        test.warning('Real name from object map #2: %s' % names2[sn])

        # Add object name of first object map:
        new_names[sn] = names1[sn]

    file = codecs.open(merged_object_map_file_name, "w", "utf-8")
    keys = sorted(new_names.keys())

    def esc(us):
        return us.encode("unicode-escape")

    # Write unique and full duplicates:
    for sn in keys:
        rn = new_names[sn]
        if (sn in names1 and sn not in names2) \
            or (sn not in names1 and sn in names2) \
            or (sn in names2 and rn == names2[sn]):
            file.write(u"%s\t%s\n" % (esc(sn), esc(rn)))

    # Write symbolic name duplicates with unique
    # real names:
    for sn in keys:
        rn = new_names[sn]
        if sn in names2 and rn != names2[sn]:
            file.write("%s\t%s\n" % (esc(sn), esc(names2[sn])))
    file.close()
test.py