All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hp.octane.integrations.uft.UftTestDiscoveryUtils Maven / Gradle / Ivy

There is a newer version: 2.24.3.5
Show newest version
/**
 * Copyright 2017-2023 Open Text
 *
 * The only warranties for products and services of Open Text and
 * its affiliates and licensors (“Open Text”) are as may be set forth
 * in the express warranty statements accompanying such products and services.
 * Nothing herein should be construed as constituting an additional warranty.
 * Open Text shall not be liable for technical or editorial errors or
 * omissions contained herein. The information contained herein is subject
 * to change without notice.
 *
 * Except as specifically indicated otherwise, this document contains
 * confidential information and a valid license is required for possession,
 * use or copying. If this work is provided to the U.S. Government,
 * consistent with FAR 12.211 and 12.212, Commercial Computer Software,
 * Computer Software Documentation, and Technical Data for Commercial Items are
 * licensed to the U.S. Government under vendor's standard commercial license.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hp.octane.integrations.uft;

import com.hp.octane.integrations.dto.executor.impl.TestingToolType;
import com.hp.octane.integrations.uft.items.*;
import com.hp.octane.integrations.utils.SdkConstants;
import com.hp.octane.integrations.utils.SdkStringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.util.StringUtil;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class UftTestDiscoveryUtils {

    private static final Logger logger = LogManager.getLogger(UftTestDiscoveryUtils.class);

    private static final String STFileExtention = ".st";//api test

    private static final String QTPFileExtention = ".tsp";//gui test

    private static final String XLSXExtention = ".xlsx";//excel file

    private static final String XLSExtention = ".xls";//excel file

    private static final String GUI_TEST_FILE = "test" + QTPFileExtention;//gui test

    private static final String API_ACTIONS_FILE = "actions.xml";//api test

    private static final String RESOURCE_MTR_FILE = "resource.mtr";//parameters file

    private static final Set SKIP_FOLDERS = Stream.of("_discovery_results").collect(Collectors.toSet());

    public static final String ACTION_0 = "action0";

    public static final String UFT_PARAM_ARG_DEFAULT_VALUE_NODE_NAME = "ArgDefaultValue";

    public static final String UFT_PARAM_ARG_NAME_NODE_NAME = "ArgName";

    public static final String UFT_PARAM_ARGUMENTS_COLLECTION_NODE_NAME = "ArgumentsCollection";

    public static final String UFT_ACTION_DESCRIPTION_NODE_NAME = "Description";

    public static final String UFT_COMPONENT_NODE_NAME = "Component";

    public static final String UFT_DEPENDENCY_NODE_NAME = "Dependency";

    public static final String UFT_ACTION_LOGICAL_ATTR = "Logical";

    public static final String UFT_ACTION_KIND_ATTR = "Kind";

    public static final String UFT_ACTION_TYPE_ATTR = "Type";

    public static final String UFT_ACTION_SCOPE_ATTR = "Scope";

    public static final String UFT_ACTION_KIND_VALUE = "16";

    public static final String UFT_ACTION_TYPE_VALUE = "1";

    public static final String UFT_ACTION_SCOPE_VALUE = "0";

    public static UftTestDiscoveryResult doFullDiscovery(File root) {
        return doFullDiscovery(root, TestingToolType.UFT);
    }

    public static UftTestDiscoveryResult doFullDiscovery(File root, TestingToolType testingToolType) {
        logger.info("Full sync requested for: {}, path: {}, ", testingToolType, root.getAbsolutePath());

        UftTestDiscoveryResult result = new UftTestDiscoveryResult();
        scanFileSystemRecursively(root, root, result, testingToolType);
        result.setFullScan(true);
        result.setTestingToolType(testingToolType);
        return result;
    }

    private static void scanFileSystemRecursively(File root, File dirPath, UftTestDiscoveryResult discoveryResult, TestingToolType testingToolType) {
        if (dirPath.isDirectory() && SKIP_FOLDERS.contains(dirPath.getName())) {
            return;
        }

        File[] paths = dirPath.isDirectory() ? dirPath.listFiles() : new File[]{dirPath};

        //if it test folder - create new test, else drill down to subFolders
        UftTestType testType = paths != null ? isUftTestFolder(paths) : UftTestType.None;
        if (!testType.isNone()) {
            // if UFT mode or (MBT mode and test type GUI)- API tests are currently not supported in MBT mode
            if (!(TestingToolType.MBT.equals(testingToolType) && (UftTestType.API.equals(testType)))) {
                AutomatedTest test = createAutomatedTest(root, dirPath, testType, testingToolType);
                discoveryResult.getAllTests().add(test);
            }
        } else if (paths != null) {
            for (File path : paths) {
                if (path.isDirectory()) {
                    scanFileSystemRecursively(root, path, discoveryResult, testingToolType);
                } else if (isUftDataTableFile(path.getName())) {
                    ScmResourceFile dataTable = createDataTable(root, path);
                    discoveryResult.getAllScmResourceFiles().add(dataTable);
                }
            }
        }
    }

    public static ScmResourceFile createDataTable(File root, File path) {
        ScmResourceFile resourceFile = new ScmResourceFile();
        resourceFile.setName(path.getName());
        resourceFile.setRelativePath(getRelativePath(root, path));
        resourceFile.setOctaneStatus(OctaneStatus.NEW);

        return resourceFile;

    }

    public static boolean isUftDataTableFile(String path) {
        String loweredPath = path.toLowerCase();
        return loweredPath.endsWith(XLSXExtention) || loweredPath.endsWith(XLSExtention);
    }

    public static UftTestType isUftTestFolder(File[] paths) {
        if (paths == null) {
            return UftTestType.None;
        }
        for (File path : paths) {
            if (path.getName().endsWith(STFileExtention)) {
                return UftTestType.API;
            }
            if (path.getName().endsWith(QTPFileExtention)) {
                return UftTestType.GUI;
            }
        }

        return UftTestType.None;
    }

    public static boolean isUftActionFile(String path) {
        String loweredPath = path.toLowerCase();
        return loweredPath.endsWith(RESOURCE_MTR_FILE);
    }

    public static boolean isTestMainFilePath(String path) {
        return !getUftTestType(path).isNone();
    }

    public static UftTestType getUftTestType(String testMainFilePath) {
        String lowerPath = testMainFilePath.toLowerCase();
        if (lowerPath.endsWith(QTPFileExtention)) {
            return UftTestType.GUI;
        }

        if (lowerPath.endsWith(STFileExtention) || lowerPath.endsWith(API_ACTIONS_FILE)) {
            return UftTestType.API;
        }

        return UftTestType.None;
    }

    public static File getTestFolderForTestMainFile(String path) {
        if (isTestMainFilePath(path)) {
            File file = new File(path);
            File parent = file.getParentFile();
            return parent;
        }
        return null;
    }

    public static AutomatedTest createAutomatedTest(File root, File dirPath, UftTestType testType, TestingToolType testingToolType) {
        AutomatedTest test = new AutomatedTest();
        test.setName(dirPath.getName());

        String relativePath = getRelativePath(root, dirPath);
        String packageName = relativePath.length() != dirPath.getName().length() ? relativePath.substring(0, relativePath.length() - dirPath.getName().length() - 1) : "";
        test.setPackage(packageName);
        test.setExecutable(true);
        test.setUftTestType(testType);

        Document testDocument = getDocument(dirPath, testType);

        String description = getTestDescription(testDocument, testType);
        description = convertToHtmlFormatIfRequired(description);
        test.setDescription(description);
        test.setOctaneStatus(OctaneStatus.NEW);

        // discover actions only for mbt testingToolType and gui tests
        if (TestingToolType.MBT.equals(testingToolType) && UftTestType.GUI.equals(testType)) {
            String actionPathPrefix = getActionPathPrefix(test, false);
            test.setActions(parseActionsAndParameters(testDocument, actionPathPrefix, test.getName(), dirPath));
        }

        return test;
    }

    // in case a test was moved and we need the action path prefix before the move then set orgPath to true
    protected static String getActionPathPrefix(AutomatedTest test, boolean orgPath) {
        return getTestPathPrefix(test, orgPath) + "\\%s:%s";
    }

    // constructs a test path that contains only the test package and name
    protected static String getTestPathPrefix(AutomatedTest test, boolean orgPath) {
        String testPackage = orgPath ? test.getOldPackage() : test.getPackage();
        String testName = orgPath ? test.getOldName() : test.getName();

        return (SdkStringUtils.isEmpty(testPackage) ? "" : testPackage + "\\") + testName;
    }

    public static String convertToHtmlFormatIfRequired(String description) {
        if (description == null || !description.contains("\n")) {
            return description;
        }
        //aaa\nbbb = >   

aaa

bbb

String[] lines = description.split("\n"); StringBuilder sb = new StringBuilder(description.length() + lines.length * 10 + 30); sb.append(""); for (String line : lines) { sb.append("

"); sb.append(line); sb.append("

"); sb.append("\n"); } sb.append(""); return sb.toString(); } private static String getRelativePath(File root, File path) { String testPath = path.getPath(); String rootPath = root.getPath(); String relativePath = testPath.replace(rootPath, ""); relativePath = SdkStringUtils.strip(relativePath, SdkConstants.FileSystem.WINDOWS_PATH_SPLITTER + SdkConstants.FileSystem.LINUX_PATH_SPLITTER); //we want all paths will be in windows style, because tests are run in windows, therefore we replace all linux splitters (/) by windows one (\) //http://stackoverflow.com/questions/23869613/how-to-replace-one-or-more-in-string-with-just relativePath = relativePath.replaceAll(SdkConstants.FileSystem.LINUX_PATH_SPLITTER, SdkConstants.FileSystem.WINDOWS_PATH_SPLITTER + SdkConstants.FileSystem.WINDOWS_PATH_SPLITTER);//str.replaceAll("/", "\\\\"); return relativePath; } /** * Extract test description from UFT GUI test. * Note : UFT API test doesn't contain description * * @param testDocument document created from the test path * @param testType GUI or API * @return test description */ public static String getTestDescription(Document testDocument, UftTestType testType) { if (Objects.isNull(testDocument) || testType.isNone()) { return null; } String description; if (UftTestType.GUI.equals(testType)) { description = getTestDescriptionFromGuiTest(testDocument); } else { description = getTestDescriptionFromAPITest(testDocument); } if (description != null) { description = description.trim(); } return description; } private static String getTestDescriptionFromAPITest(Document document) { //Actions.xml // // // NodeList actions = document.getElementsByTagName("Action"); for (int temp = 0; temp < actions.getLength(); temp++) { Node nNode = actions.item(temp); NamedNodeMap attributes = nNode.getAttributes(); Node internalNameAttr = attributes.getNamedItem("internalName"); if (internalNameAttr != null && "MainAction".equals(internalNameAttr.getNodeValue())) { return attributes.getNamedItem("description").getNodeValue(); } } return null; } private static String getTestDescriptionFromGuiTest(Document document) { return document.getElementsByTagName("Description").item(0).getTextContent(); } public static String extractXmlContentFromTspFile(InputStream stream) throws IOException { POIFSFileSystem poiFS = new POIFSFileSystem(stream); DirectoryNode root = poiFS.getRoot(); String xmlData = ""; for (Entry entry : root) { String name = entry.getName(); if ("ComponentInfo".equals(name)) { if (entry instanceof DirectoryEntry) { System.out.println(entry); } else if (entry instanceof DocumentEntry) { byte[] content = new byte[((DocumentEntry) entry).getSize()]; int readBytes = poiFS.createDocumentInputStream("ComponentInfo").read(content); if (readBytes < content.length) { // [YG] probably should handle this case and continue to read logger.warn("expected to read " + content.length + " bytes, but read and stopped after " + readBytes); } String fromUnicodeLE = StringUtil.getFromUnicodeLE(content); xmlData = fromUnicodeLE.substring(fromUnicodeLE.indexOf('<')).replaceAll("\u0000", ""); } } } return xmlData; } public static Document getDocument(File dirPath, UftTestType testType) { if (Objects.isNull(dirPath) || !dirPath.exists()) { logger.error("test path is expected to be non null or exist"); return null; } try { if (UftTestType.GUI.equals(testType)) { return getGuiTestDocument(dirPath); } else { return getApiTestDocument(dirPath); } } catch (Exception e) { logger.error("Failed to create document for path: {}, test type: {}", dirPath.getPath(), testType.name(), e); return null; } } private static Document getGuiTestDocument(File dirPath) throws IOException, ParserConfigurationException, SAXException { File tspTestFile = getFileIfExist(dirPath, GUI_TEST_FILE); if (tspTestFile == null) { return null; } InputStream is = new FileInputStream(tspTestFile); String xmlContent = extractXmlContentFromTspFile(is); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); return documentBuilder.parse(new InputSource(new StringReader(xmlContent))); } private static Document getApiTestDocument(File dirPath) throws ParserConfigurationException, IOException, SAXException { File actionsFile = getFileIfExist(dirPath, API_ACTIONS_FILE); if (actionsFile == null) { return null; } DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); return dBuilder.parse(actionsFile); } private static File getFileIfExist(File dirPath, String fileName) { if(SystemUtils.IS_OS_LINUX) { Optional optionalFile = Arrays.stream(dirPath.listFiles()).filter(file -> file.getName().equalsIgnoreCase(fileName)).findFirst(); if(optionalFile.isPresent()) { return optionalFile.get(); } else { logger.warn("File {} does not exist", dirPath.getAbsolutePath() + File.separator + fileName); } } else { File file = new File(dirPath, fileName); if(file.exists()) { return file; } else { logger.warn("File {} does not exist", file.getAbsolutePath()); } } return null; } private static List parseActionsAndParameters(Document document, String actionPathPrefix, String testName, File dirPath) { List actions = new ArrayList<>(); if (Objects.isNull(document)) { logger.warn("received null gui test document, actions will not be parsed"); } else { Map actionMap = parseActionComponents(document, testName); fillActionsLogicalName(document, actionMap, actionPathPrefix); actions.addAll(actionMap.values()); try { readParameters(dirPath, actionMap); } catch (IOException | ParserConfigurationException | SAXException e) { logger.error("failed to parse action's parameters", e); } } return actions; } private static Map parseActionComponents(Document document, String testName) { Map actionMap = new HashMap<>(); NodeList componentNodes = document.getElementsByTagName(UFT_COMPONENT_NODE_NAME); Node componentNode; for (int i = 0; i < componentNodes.getLength(); i++) { componentNode = componentNodes.item(i); String actionName = componentNode.getTextContent(); if (!actionName.equalsIgnoreCase(ACTION_0)) { // filter action0 UftTestAction action = new UftTestAction(); action.setName(actionName); action.setTestName(testName); actionMap.put(actionName, action); } } return actionMap; } private static void fillActionsLogicalName(Document document, Map actionMap, String actionPathPrefix) { NodeList dependencyNodes = document.getElementsByTagName(UFT_DEPENDENCY_NODE_NAME); Node dependencyNode; NamedNodeMap attributes; for (int i = 0; i < dependencyNodes.getLength(); i++) { dependencyNode = dependencyNodes.item(i); attributes = dependencyNode.getAttributes(); String type = attributes.getNamedItem(UFT_ACTION_TYPE_ATTR).getNodeValue(); String kind = attributes.getNamedItem(UFT_ACTION_KIND_ATTR).getNodeValue(); String scope = attributes.getNamedItem(UFT_ACTION_SCOPE_ATTR).getNodeValue(); String logicalName = attributes.getNamedItem(UFT_ACTION_LOGICAL_ATTR).getNodeValue(); if (type.equals(UFT_ACTION_TYPE_VALUE) && kind.equals(UFT_ACTION_KIND_VALUE) && scope.equals(UFT_ACTION_SCOPE_VALUE) && SdkStringUtils.isNotEmpty(logicalName)) { String dependencyStr = dependencyNode.getTextContent(); String actionName = dependencyStr.substring(0, dependencyStr.indexOf("\\")); if (!actionName.equalsIgnoreCase(ACTION_0)) { // action0 is not relevant UftTestAction action = actionMap.get(actionName); action.setLogicalName(logicalName); setActionPath(action, actionPathPrefix); } } } } // repository path is of the following format: // \\: private static void setActionPath(UftTestAction action, String actionPathPrefix) { String actionName = SdkStringUtils.isEmpty(action.getLogicalName()) ? action.getName() : action.getLogicalName(); action.setRepositoryPath(String.format(actionPathPrefix, action.getName(), actionName)); } private static void readParameters(File testDirPath, Map actionMap) throws IOException, ParserConfigurationException, SAXException { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); for (Map.Entry entry : actionMap.entrySet()) { String actionName = entry.getKey(); File actionFolder = new File(testDirPath, actionName); if (actionFolder.exists()) { File resourceMtrFile = getFileIfExist(actionFolder, RESOURCE_MTR_FILE); if (resourceMtrFile != null) { parseActionMtrFile(resourceMtrFile, documentBuilder, entry.getValue()); } else { logger.warn("resource.mtr file for action {} does not exist", actionName); } } else { entry.getValue().setParameters(Collections.emptyList()); logger.warn("folder for action {} does not exist", actionName); } } } private static void parseActionMtrFile(File resourceMtrFile, DocumentBuilder documentBuilder, UftTestAction action) throws IOException, SAXException { List parameters = new ArrayList<>(); InputStream is = new FileInputStream(resourceMtrFile); String xmlContent = extractXmlContentFromTspFile(is); Document document = documentBuilder.parse(new InputSource(new StringReader(xmlContent))); NodeList argumentsCollectionElement = document.getElementsByTagName(UFT_PARAM_ARGUMENTS_COLLECTION_NODE_NAME); if (argumentsCollectionElement.getLength() > 0) { Node argumentsCollectionItem = argumentsCollectionElement.item(0); NodeList childArgumentElements = argumentsCollectionItem.getChildNodes(); for (int i = 0; i < childArgumentElements.getLength(); i++) { Element argumentElement = (Element) childArgumentElements.item(i); UftTestParameter parameter = new UftTestParameter(); parameter.setName(argumentElement.getElementsByTagName(UFT_PARAM_ARG_NAME_NODE_NAME).item(0).getTextContent()); parameter.setDirection(UftParameterDirection.get(Integer.parseInt(argumentElement.getElementsByTagName("ArgDirection").item(0).getTextContent()))); Node defaultValueNode = argumentElement.getElementsByTagName(UFT_PARAM_ARG_DEFAULT_VALUE_NODE_NAME).item(0); if (null != defaultValueNode) { parameter.setDefaultValue(defaultValueNode.getTextContent()); } parameters.add(parameter); } } action.setParameters(parameters); String description = document.getElementsByTagName(UFT_ACTION_DESCRIPTION_NODE_NAME).item(0).getTextContent(); action.setDescription(description); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy