示例#1
0
        /// <summary>
        /// creates instance of the runner given a source.
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="timeout"></param>
        /// <param name="backgroundWorker"></param>
        /// <param name="useUFTLicense"></param>
        public FileSystemTestsRunner(List <string> sources,
                                     TimeSpan timeout,
                                     int ControllerPollingInterval,
                                     TimeSpan perScenarioTimeOutMinutes,
                                     List <string> ignoreErrorStrings,
                                     Dictionary <string, string> jenkinsEnvVariables,
                                     McConnectionInfo mcConnection,
                                     string mobileInfo,
                                     bool useUFTLicense = false
                                     )
        {
            _jenkinsEnvVariables = jenkinsEnvVariables;
            //search if we have any testing tools installed
            if (!Helper.IsTestingToolsInstalled(TestStorageType.FileSystem))
            {
                ConsoleWriter.WriteErrLine(string.Format(Resources.FileSystemTestsRunner_No_HP_testing_tool_is_installed_on, System.Environment.MachineName));
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            _timeout = timeout;
            ConsoleWriter.WriteLine("FileSystemTestRunner timeout is " + _timeout);
            _stopwatch = Stopwatch.StartNew();

            _pollingInterval           = ControllerPollingInterval;
            _perScenarioTimeOutMinutes = perScenarioTimeOutMinutes;
            _ignoreErrorStrings        = ignoreErrorStrings;


            _useUFTLicense = useUFTLicense;
            _tests         = new List <TestInfo>();

            _mcConnection             = mcConnection;
            _mobileInfoForAllGuiTests = mobileInfo;

            ConsoleWriter.WriteLine("Mc connection info is - " + _mcConnection.ToString());

            //go over all sources, and create a list of all tests
            foreach (string source in sources)
            {
                List <TestInfo> testGroup = new List <TestInfo>();
                try
                {
                    //--handle directories which contain test subdirectories (recursively)
                    if (Helper.IsDirectory(source))
                    {
                        var testsLocations = Helper.GetTestsLocations(source);
                        foreach (var loc in testsLocations)
                        {
                            var test = new TestInfo(loc, loc, source);
                            testGroup.Add(test);
                        }
                    }
                    //--handle mtb files (which contain links to tests)
                    else
                    //file might be LoadRunner scenario or
                    //mtb file (which contain links to tests)
                    //other files are dropped
                    {
                        testGroup = new List <TestInfo>();
                        FileInfo fi = new FileInfo(source);
                        if (fi.Extension == Helper.LoadRunnerFileExtention)
                        {
                            testGroup.Add(new TestInfo(source, source, source));
                        }
                        else if (fi.Extension == ".mtb")
                        //if (source.TrimEnd().EndsWith(".mtb", StringComparison.CurrentCultureIgnoreCase))
                        {
                            MtbManager manager = new MtbManager();
                            var        paths   = manager.Parse(source);
                            foreach (var p in paths)
                            {
                                testGroup.Add(new TestInfo(p, p, source));
                            }
                        }
                        else if (fi.Extension == ".mtbx")
                        //if (source.TrimEnd().EndsWith(".mtb", StringComparison.CurrentCultureIgnoreCase))
                        {
                            testGroup = MtbxManager.Parse(source, _jenkinsEnvVariables, source);
                        }
                    }
                }
                catch (Exception)
                {
                    testGroup = new List <TestInfo>();
                }

                //--handle single test dir, add it with no group
                if (testGroup.Count == 1)
                {
                    testGroup[0].TestGroup = "<None>";
                }

                _tests.AddRange(testGroup);
            }

            if (_tests == null || _tests.Count == 0)
            {
                ConsoleWriter.WriteLine(Resources.FsRunnerNoValidTests);
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerTestsFound, _tests.Count));
            _tests.ForEach(t => ConsoleWriter.WriteLine("" + t.TestName));
            ConsoleWriter.WriteLine(Resources.GeneralDoubleSeperator);
        }
示例#2
0
        public static List <TestInfo> LoadMtbx(string xmlContent, Dictionary <string, string> jankinsEnvironmentVars, string testGroupName)
        {
            var localEnv = Environment.GetEnvironmentVariables();

            foreach (string varName in localEnv.Keys)
            {
                string value = (string)localEnv[varName];
                xmlContent = ReplaceString(xmlContent, "%" + varName + "%", value, StringComparison.OrdinalIgnoreCase);
                xmlContent = ReplaceString(xmlContent, "${" + varName + "}", value, StringComparison.OrdinalIgnoreCase);
            }

            if (jankinsEnvironmentVars != null)
            {
                foreach (string varName in jankinsEnvironmentVars.Keys)
                {
                    string value = jankinsEnvironmentVars[varName];
                    xmlContent = ReplaceString(xmlContent, "%" + varName + "%", value, StringComparison.OrdinalIgnoreCase);
                    xmlContent = ReplaceString(xmlContent, "${" + varName + "}", value, StringComparison.OrdinalIgnoreCase);
                }
            }

            List <TestInfo> retval = new List <TestInfo>();
            XDocument       doc    = XDocument.Parse(xmlContent);

            XmlSchemaSet schemas = new XmlSchemaSet();

            var assembly = Assembly.GetExecutingAssembly();

            var schemaStream = assembly.GetManifestResourceStream("HpToolsLauncher.MtbxSchema.xsd");

            XmlSchema schema = XmlSchema.Read(schemaStream, null);

            schemas.Add(schema);

            string validationMessages = "";

            doc.Validate(schemas, (o, e) =>
            {
                validationMessages += e.Message + Environment.NewLine;
            });

            if (!string.IsNullOrWhiteSpace(validationMessages))
            {
                ConsoleWriter.WriteLine("mtbx schema validation errors: " + validationMessages);
            }
            try
            {
                var root = doc.Root;
                foreach (var test in GetElements(root, "Test"))
                {
                    string path = GetAttribute(test, "path").Value;

                    if (!Directory.Exists(path))
                    {
                        string line = string.Format(Resources.GeneralFileNotFound, path);
                        ConsoleWriter.WriteLine(line);
                        ConsoleWriter.ErrorSummaryLines.Add(line);
                        Launcher.ExitCode = Launcher.ExitCodeEnum.Failed;
                        continue;
                    }

                    XAttribute xname = GetAttribute(test, "name");

                    string name = "<None>";
                    if (xname != null)
                    {
                        name = xname.Value;
                    }

                    TestInfo         col        = new TestInfo(path, name, testGroupName);
                    HashSet <string> paramNames = new HashSet <string>();

                    foreach (var param in GetElements(test, "Parameter"))
                    {
                        string     pname  = GetAttribute(param, "name").Value;
                        string     pval   = GetAttribute(param, "value").Value;
                        XAttribute xptype = GetAttribute(param, "type");
                        string     ptype  = "string";

                        if (xptype != null)
                        {
                            ptype = xptype.Value;
                        }

                        var testParam = new TestParameterInfo()
                        {
                            Name = pname, Type = ptype, Value = pval
                        };
                        if (!paramNames.Contains(testParam.Name))
                        {
                            paramNames.Add(testParam.Name);
                            col.ParameterList.Add(testParam);
                        }
                        else
                        {
                            string line = string.Format(Resources.GeneralDuplicateParameterWarning, pname, path);
                            ConsoleWriter.WriteLine(line);
                        }
                    }

                    XElement dataTable = GetElement(test, "DataTable");
                    if (dataTable != null)
                    {
                        col.DataTablePath = GetAttribute(dataTable, "path").Value;
                    }

                    retval.Add(col);
                }
            }
            catch (Exception ex)
            {
                ConsoleWriter.WriteException("Problem while parsing Mtbx file", ex);
            }
            return(retval);
        }
示例#3
0
        /// <summary>
        /// creates a correct type of runner and runs a single test.
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <returns></returns>
        private TestRunResults RunHPToolsTest(TestInfo testinf, ref string errorReason)
        {
            var testPath = testinf.TestPath;
            var type     = Helper.GetTestType(testPath);

            // if we have at least one environment for parallel runner,
            // then it must be enabled
            var isParallelRunnerEnabled = _parallelRunnerEnvironments.Count > 0;

            if (isParallelRunnerEnabled && type == TestType.QTP)
            {
                type = TestType.ParallelRunner;
            }
            // if the current test is an api test ignore the parallel runner flag
            // and just continue as usual
            else if (isParallelRunnerEnabled && type == TestType.ST)
            {
                ConsoleWriter.WriteLine("ParallelRunner does not support API tests, treating as normal test.");
            }

            IFileSysTestRunner runner = null;

            switch (type)
            {
            case TestType.ST:
                runner = new ApiTestRunner(this, _timeout - _stopwatch.Elapsed);
                break;

            case TestType.QTP:
                runner = new GuiTestRunner(this, _useUFTLicense, _timeout - _stopwatch.Elapsed, _uftRunMode, _mcConnection, _mobileInfoForAllGuiTests);
                break;

            case TestType.LoadRunner:
                AppDomain.CurrentDomain.AssemblyResolve += Helper.HPToolsAssemblyResolver;
                runner = new PerformanceTestRunner(this, _timeout, _pollingInterval, _perScenarioTimeOutMinutes, _ignoreErrorStrings, _displayController, _analysisTemplate, _summaryDataLogger, _scriptRTSSet);
                break;

            case TestType.ParallelRunner:
                runner = new ParallelTestRunner(this, _timeout - _stopwatch.Elapsed, _mcConnection, _mobileInfoForAllGuiTests, _parallelRunnerEnvironments);
                break;
            }

            if (runner != null)
            {
                if (!_colRunnersForCleanup.ContainsKey(type))
                {
                    _colRunnersForCleanup.Add(type, runner);
                }

                Stopwatch s = Stopwatch.StartNew();

                var results = runner.RunTest(testinf, ref errorReason, RunCancelled);

                results.Runtime = s.Elapsed;
                if (type == TestType.LoadRunner)
                {
                    AppDomain.CurrentDomain.AssemblyResolve -= Helper.HPToolsAssemblyResolver;
                }

                return(results);
            }

            //check for abortion
            if (System.IO.File.Exists(_abortFilename))
            {
                ConsoleWriter.WriteLine(Resources.GeneralStopAborted);

                //stop working
                Environment.Exit((int)Launcher.ExitCodeEnum.Aborted);
            }

            return(new TestRunResults {
                ErrorDesc = "Unknown TestType", TestState = TestState.Error
            });
        }
示例#4
0
        /// <summary>
        /// runs the given test
        /// </summary>
        /// <param name="testinf"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCancelled">cancellation delegate, holds the function that checks cancellation</param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCancelled)
        {
            TestRunResults runDesc = new TestRunResults();

            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testinf.TestPath);

            runDesc.TestPath = testinf.TestPath;

            // default report location is the test path
            runDesc.ReportLocation = testinf.TestPath;

            // check if the report path has been defined
            if (!String.IsNullOrEmpty(testinf.ReportPath))
            {
                if (!Helper.TrySetTestReportPath(runDesc, testinf, ref errorReason))
                {
                    return(runDesc);
                }
            }

            runDesc.ErrorDesc = errorReason;
            runDesc.TestState = TestState.Unknown;
            if (!Helper.IsServiceTestInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.LauncherStNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            _runCancelled = runCancelled;
            if (!_stCanRun)
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                return(runDesc);
            }
            string fileName = Path.Combine(_stExecuterPath, STRunnerName);

            if (!File.Exists(fileName))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                ConsoleWriter.WriteErrLine(Resources.STExecuterNotFound);
                return(runDesc);
            }

            //write the input parameter xml file for the API test
            string paramFileName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 10);
            string tempPath      = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestParams");

            Directory.CreateDirectory(tempPath);
            string paramsFilePath   = Path.Combine(tempPath, "params" + paramFileName + ".xml");
            string paramFileContent = testinf.GenerateAPITestXmlForTest();

            string argumentString = "";

            if (!string.IsNullOrWhiteSpace(paramFileContent))
            {
                File.WriteAllText(paramsFilePath, paramFileContent);
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\" {4} \"{5}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation, STRunnerInputParamsArg, paramsFilePath);
            }
            else
            {
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation);
            }

            Stopwatch s = Stopwatch.StartNew();

            runDesc.TestState = TestState.Running;

            if (!ExecuteProcess(fileName,
                                argumentString,
                                ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
            }
            else
            {
                runDesc.ReportLocation = Path.Combine(runDesc.ReportLocation, "Report");
                if (!File.Exists(Path.Combine(runDesc.ReportLocation, "Results.xml")) && !File.Exists(Path.Combine(runDesc.ReportLocation, "run_results.html")))
                {
                    runDesc.TestState = TestState.Error;
                    runDesc.ErrorDesc = "No Results.xml or run_results.html file found";
                }
            }
            //File.Delete(paramsFilePath);
            runDesc.Runtime = s.Elapsed;
            return(runDesc);
        }
        /// <summary>
        /// runs the given test and returns resutls
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCanclled"></param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCanclled)
        {
            var testPath = testinf.TestPath;
            TestRunResults runDesc = new TestRunResults();
            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testPath);
            runDesc.ReportLocation = testPath;

            runDesc.TestPath = testPath;
            runDesc.TestState = TestState.Unknown;

            _runCancelled = runCanclled;

            if (!Helper.IsQtpInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.GeneralQtpNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return runDesc;
            }

            try
            {
                ChangeDCOMSettingToInteractiveUser();
                var type = Type.GetTypeFromProgID("Quicktest.Application");

                lock (_lockObject)
                {
                    _qtpApplication = Activator.CreateInstance(type) as Application;

                    Version qtpVersion = Version.Parse(_qtpApplication.Version);
                    if (qtpVersion.Equals(new Version(11, 0)))
                    {
                        runDesc.ReportLocation = Path.Combine(testPath, "Report");
                        if (Directory.Exists(runDesc.ReportLocation))
                        {
                            Directory.Delete(runDesc.ReportLocation, true);
                            Directory.CreateDirectory(runDesc.ReportLocation);
                        }
                    }

                    // Check for required Addins
                    LoadNeededAddins(testPath);

                    if (!_qtpApplication.Launched)
                    {
                        if (_runCancelled())
                        {
                            QTPTestCleanup();
                            KillQtp();
                            runDesc.TestState = TestState.Error;
                            return runDesc;
                        }
                        // Launch application after set Addins
                        _qtpApplication.Launch();
                        _qtpApplication.Visible = false;

                    }
                }
            }
            catch (Exception e)
            {
                errorReason = Resources.QtpNotLaunchedError;
                runDesc.TestState = TestState.Error;
                runDesc.ReportLocation = "";
                runDesc.ErrorDesc = e.Message;
                return runDesc;
            }

            if (_qtpApplication.Test != null && _qtpApplication.Test.Modified)
            {
                var message = Resources.QtpNotLaunchedError;
                errorReason = message;
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return runDesc;
            }

            _qtpApplication.UseLicenseOfType(_useUFTLicense
                                                 ? tagUnifiedLicenseType.qtUnifiedFunctionalTesting
                                                 : tagUnifiedLicenseType.qtNonUnified);

            if (!HandleInputParameters(testPath, ref errorReason, testinf.GetParameterDictionaryForQTP()))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return runDesc;
            }

            GuiTestRunResult guiTestRunResult = ExecuteQTPRun(runDesc);
            runDesc.ReportLocation = guiTestRunResult.ReportPath;

            if (!guiTestRunResult.IsSuccess)
            {
                runDesc.TestState = TestState.Error;
                return runDesc;
            }

            if (!HandleOutputArguments(ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return runDesc;
            }

            QTPTestCleanup();

            return runDesc;
        }
        /// <summary>
        /// creates instance of the runner given a source.
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="timeout"></param>
        /// <param name="scriptRtsSet"></param>
        /// <param name="reportPath">The report base directory for all running tests.</param>
        /// <param name="controllerPollingInterval"></param>
        /// <param name="perScenarioTimeOutMinutes"></param>
        /// <param name="ignoreErrorStrings"></param>
        /// <param name="jenkinsEnvVariables"></param>
        /// <param name="mcConnection"></param>
        /// <param name="mobileInfo"></param>
        /// <param name="parallelRunnerEnvironments"></param>
        /// <param name="displayController"></param>
        /// <param name="analysisTemplate"></param>
        /// <param name="summaryDataLogger"></param>
        /// <param name="useUftLicense"></param>
        public FileSystemTestsRunner(List <TestData> sources,
                                     TimeSpan timeout,
                                     int controllerPollingInterval,
                                     TimeSpan perScenarioTimeOutMinutes,
                                     List <string> ignoreErrorStrings,
                                     Dictionary <string, string> jenkinsEnvVariables,
                                     McConnectionInfo mcConnection,
                                     string mobileInfo,
                                     Dictionary <string, List <string> > parallelRunnerEnvironments,
                                     bool displayController,
                                     string analysisTemplate,
                                     SummaryDataLogger summaryDataLogger,
                                     List <ScriptRTSModel> scriptRtsSet,
                                     string reportPath,
                                     bool useUftLicense = false)
        {
            _jenkinsEnvVariables = jenkinsEnvVariables;
            //search if we have any testing tools installed
            if (!Helper.IsTestingToolsInstalled(TestStorageType.FileSystem))
            {
                ConsoleWriter.WriteErrLine(string.Format(Resources.FileSystemTestsRunner_No_HP_testing_tool_is_installed_on, System.Environment.MachineName));
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            _timeout = timeout;
            ConsoleWriter.WriteLine("FileSystemTestRunner timeout is " + _timeout);
            _stopwatch = Stopwatch.StartNew();

            _pollingInterval           = controllerPollingInterval;
            _perScenarioTimeOutMinutes = perScenarioTimeOutMinutes;
            _ignoreErrorStrings        = ignoreErrorStrings;

            _useUFTLicense     = useUftLicense;
            _displayController = displayController;
            _analysisTemplate  = analysisTemplate;
            _summaryDataLogger = summaryDataLogger;
            _scriptRTSSet      = scriptRtsSet;
            _tests             = new List <TestInfo>();

            _mcConnection             = mcConnection;
            _mobileInfoForAllGuiTests = mobileInfo;

            _parallelRunnerEnvironments = parallelRunnerEnvironments;

            if (!string.IsNullOrWhiteSpace(_mcConnection.MobileHostAddress))
            {
                ConsoleWriter.WriteLine("UFT Mobile connection info is - " + _mcConnection.ToString());
            }

            if (reportPath != null)
            {
                ConsoleWriter.WriteLine("Results base directory (for all tests) is: " + reportPath);
            }

            //go over all sources, and create a list of all tests
            foreach (TestData source in sources)
            {
                List <TestInfo> testGroup = new List <TestInfo>();
                try
                {
                    //--handle directories which contain test subdirectories (recursively)
                    if (Helper.IsDirectory(source.Tests))
                    {
                        var testsLocations = Helper.GetTestsLocations(source.Tests);
                        foreach (var loc in testsLocations)
                        {
                            var test = new TestInfo(loc, loc, source.Tests, source.Id)
                            {
                                ReportPath = source.ReportPath
                            };
                            testGroup.Add(test);
                        }
                    }
                    //--handle mtb files (which contain links to tests)
                    else
                    //file might be LoadRunner scenario or
                    //mtb file (which contain links to tests)
                    //other files are dropped
                    {
                        testGroup = new List <TestInfo>();
                        FileInfo fi = new FileInfo(source.Tests);
                        if (fi.Extension == Helper.LoadRunnerFileExtention)
                        {
                            testGroup.Add(new TestInfo(source.Tests, source.Tests, source.Tests, source.Id)
                            {
                                ReportPath = source.ReportPath
                            });
                        }
                        else if (fi.Extension == ".mtb")
                        //if (source.TrimEnd().EndsWith(".mtb", StringComparison.CurrentCultureIgnoreCase))
                        {
                            MtbManager manager = new MtbManager();
                            var        paths   = manager.Parse(source.Tests);
                            foreach (var p in paths)
                            {
                                testGroup.Add(new TestInfo(p, p, source.Tests, source.Id));
                            }
                        }
                        else if (fi.Extension == ".mtbx")
                        {
                            testGroup = MtbxManager.Parse(source.Tests, _jenkinsEnvVariables, source.Tests);

                            // set the test Id for each test from the group
                            // this is important for parallel runner
                            foreach (var testInfo in testGroup)
                            {
                                testInfo.TestId = source.Id;
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    testGroup = new List <TestInfo>();
                }

                //--handle single test dir, add it with no group
                if (testGroup.Count == 1)
                {
                    testGroup[0].TestGroup = "Test group";
                }

                _tests.AddRange(testGroup);
            }

            if (_tests == null || _tests.Count == 0)
            {
                ConsoleWriter.WriteLine(Resources.FsRunnerNoValidTests);
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            // if a custom path was provided,set the custom report path for all the valid tests(this will overwrite the default location)
            if (reportPath != null)
            {
                foreach (TestInfo t in _tests)
                {
                    if (string.IsNullOrWhiteSpace(t.ReportBaseDirectory))
                    {
                        t.ReportBaseDirectory = reportPath;
                    }
                }
            }

            ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerTestsFound, _tests.Count));

            foreach (var test in _tests)
            {
                ConsoleWriter.WriteLine("" + test.TestName);
                if (parallelRunnerEnvironments.ContainsKey(test.TestId))
                {
                    parallelRunnerEnvironments[test.TestId].ForEach(
                        env => ConsoleWriter.WriteLine("    " + env));
                }
            }

            ConsoleWriter.WriteLine(Resources.GeneralDoubleSeperator);
        }
        /// <summary>
        /// runs all tests given to this runner and returns a suite of run resutls
        /// </summary>
        /// <returns>The rest run results for each test</returns>
        public override TestSuiteRunResults Run()
        {
            //create a new Run Results object
            TestSuiteRunResults activeRunDesc = new TestSuiteRunResults();
            TestInfo            firstTest     = _tests[0];

            double totalTime = 0;
            var    start     = DateTime.Now;

            KillAllAborterProcesses();
            Process aborter = StartHPToolsAborter();

            DateTime robotAlive = DateTime.Now;

            try
            {
                LogCleanupTestInfo();

                foreach (var test in _tests)
                {
                    if (IsRobotTooLongAlive(robotAlive))
                    {
                        RunRobotCleanup();
                        robotAlive = DateTime.Now;
                    }

                    if (IsTestPlaceholder(test))
                    {
                        continue;
                    }
                    if (RunCancelled())
                    {
                        break;
                    }

                    TestRunResults runResult = null;

                    runResult = ExecuteTest(test);
                    if (RunCancelled())
                    {
                        break;
                    }

                    if (IsTestFailed(runResult) && IsCleanupTestDefined() && !IsCleanupTest(test))
                    {
                        Console.WriteLine("Test Failed: CLEANUP AND RE-RUN");
                        RunRobotCleanup();
                        ExecuteTest(GetCleanupTest());

                        if (RunCancelled())
                        {
                            break;
                        }
                        runResult = ExecuteTest(test);
                    }

                    activeRunDesc.TestRuns.Add(runResult);
                    AnalyzeRunResult(runResult);
                }
            }
            catch (Exception)
            {
                //Ignore
            }
            finally
            {
                if (!aborter.HasExited)
                {
                    aborter.Kill();
                }

                totalTime = (DateTime.Now - start).TotalSeconds;
                activeRunDesc.NumTests     = _tests.Count;
                activeRunDesc.NumErrors    = _errors;
                activeRunDesc.TotalRunTime = TimeSpan.FromSeconds(totalTime);
                activeRunDesc.NumFailures  = _fail;

                RunRobotCleanup();
            }

            return(activeRunDesc);
        }
        /// <summary>
        /// creates a correct type of runner and runs a single test.
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <returns></returns>
        private TestRunResults RunHPToolsTest(TestInfo testinf, ref string errorReason)
        {
            var testPath = testinf.TestPath;
            var type = Helper.GetTestType(testPath);
            IFileSysTestRunner runner = null;
            switch (type)
            {
                case TestType.ST:
                    runner = new ApiTestRunner(this, _timeout - _stopwatch.Elapsed);
                    break;
                case TestType.QTP:
                    runner = new GuiTestRunner(this, _useUFTLicense, _timeout - _stopwatch.Elapsed);
                    break;
                case TestType.LoadRunner:
                    AppDomain.CurrentDomain.AssemblyResolve += Helper.HPToolsAssemblyResolver;
                    runner = new PerformanceTestRunner(this, _timeout, _pollingInterval, _perScenarioTimeOutMinutes, _ignoreErrorStrings);
                    break;
            }

            if (runner != null)
            {
                if (!_colRunnersForCleanup.ContainsKey(type))
                    _colRunnersForCleanup.Add(type, runner);

                Stopwatch s = Stopwatch.StartNew();

                TestRunResults results = null;

                results = runner.RunTest(testinf, ref errorReason, RunCancelled);

                results.Runtime = s.Elapsed;
                if (type == TestType.LoadRunner)
                    AppDomain.CurrentDomain.AssemblyResolve -= Helper.HPToolsAssemblyResolver;

                return results;
            }

            //check for abortion
            if (System.IO.File.Exists(_abortFilename))
            {

                ConsoleWriter.WriteLine(Resources.GeneralStopAborted);

                //stop working
                Environment.Exit((int)Launcher.ExitCodeEnum.Aborted);
            }

            return new TestRunResults { ErrorDesc = "Unknown TestType", TestState = TestState.Error };
        }
        public static List<TestInfo> LoadMtbx(string xmlContent, Dictionary<string, string> jankinsEnvironmentVars, string testGroupName)
        {
            var localEnv = Environment.GetEnvironmentVariables();

            foreach (string varName in localEnv.Keys)
            {
                string value = (string)localEnv[varName];
                xmlContent = ReplaceString(xmlContent, "%" + varName + "%", value, StringComparison.OrdinalIgnoreCase);
                xmlContent = ReplaceString(xmlContent, "${" + varName + "}", value, StringComparison.OrdinalIgnoreCase);
            }

            if (jankinsEnvironmentVars != null)
            {
                foreach (string varName in jankinsEnvironmentVars.Keys)
                {
                    string value = jankinsEnvironmentVars[varName];
                    xmlContent = ReplaceString(xmlContent, "%" + varName + "%", value, StringComparison.OrdinalIgnoreCase);
                    xmlContent = ReplaceString(xmlContent, "${" + varName + "}", value, StringComparison.OrdinalIgnoreCase);
                }
            }

            List<TestInfo> retval = new List<TestInfo>();
            XDocument doc = XDocument.Parse(xmlContent);

            XmlSchemaSet schemas = new XmlSchemaSet();

            var assembly = Assembly.GetExecutingAssembly();

            var schemaStream = assembly.GetManifestResourceStream("HpToolsLauncher.MtbxSchema.xsd");

            XmlSchema schema = XmlSchema.Read(schemaStream, null);

            schemas.Add(schema);

            string validationMessages = "";
            doc.Validate(schemas, (o, e) =>
            {
                validationMessages += e.Message + Environment.NewLine;
            });

            if (!string.IsNullOrWhiteSpace(validationMessages))
                ConsoleWriter.WriteLine("mtbx schema validation errors: " + validationMessages);
            try
            {
                var root = doc.Root;
                foreach (var test in GetElements(root, "Test"))
                {
                    string path = GetAttribute(test, "path").Value;

                    if (!Directory.Exists(path))
                    {
                        string line = string.Format(Resources.GeneralFileNotFound, path);
                        ConsoleWriter.WriteLine(line);
                        ConsoleWriter.ErrorSummaryLines.Add(line);
                        Launcher.ExitCode = Launcher.ExitCodeEnum.Failed;
                        continue;
                    }

                    XAttribute xname = GetAttribute(test, "name");

                    string name = "<None>";
                    if (xname != null)
                        name = xname.Value;

                    TestInfo col = new TestInfo(path, name, testGroupName);
                    HashSet<string> paramNames = new HashSet<string>();

                    foreach (var param in GetElements(test, "Parameter"))
                    {
                        
                        string pname = GetAttribute(param, "name").Value;
                        string pval = GetAttribute(param, "value").Value;
                        XAttribute xptype = GetAttribute(param, "type");
                        string ptype = "string";

                        if (xptype != null)
                            ptype = xptype.Value;

                        var testParam = new TestParameterInfo() { Name = pname, Type = ptype, Value = pval };
                        if (!paramNames.Contains(testParam.Name))
                        {
                            paramNames.Add(testParam.Name);
                            col.ParameterList.Add(testParam);
                        }
                        else
                        {
                            string line = string.Format(Resources.GeneralDuplicateParameterWarning, pname, path);
                            ConsoleWriter.WriteLine(line);
                        }
                    }

                    retval.Add(col);
                }
            }
            catch (Exception ex)
            {
                ConsoleWriter.WriteException("Problem while parsing Mtbx file", ex);
            }
            return retval;
        }
        /// <summary>
        /// runs the given test and returns resutls
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCanclled"></param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCanclled)
        {
            var            testPath = testinf.TestPath;
            TestRunResults runDesc  = new TestRunResults();

            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testPath);

            runDesc.TestPath = testPath;

            // default report location is the test path
            runDesc.ReportLocation = testPath;

            // check if the report path has been defined
            if (!String.IsNullOrEmpty(testinf.ReportPath))
            {
                if (!Helper.TrySetTestReportPath(runDesc, testinf, ref errorReason))
                {
                    return(runDesc);
                }
            }

            runDesc.TestState = TestState.Unknown;

            _runCancelled = runCanclled;

            if (!Helper.IsQtpInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.GeneralQtpNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            string reason = string.Empty;

            if (!Helper.CanUftProcessStart(out reason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = reason;
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            try
            {
                ChangeDCOMSettingToInteractiveUser();
                var type = Type.GetTypeFromProgID("Quicktest.Application");

                lock (_lockObject)
                {
                    _qtpApplication = Activator.CreateInstance(type) as Application;

                    Version qtpVersion = Version.Parse(_qtpApplication.Version);
                    if (qtpVersion.Equals(new Version(11, 0)))
                    {
                        // use the defined report path if provided
                        if (!String.IsNullOrEmpty(testinf.ReportPath))
                        {
                            runDesc.ReportLocation = Path.Combine(testinf.ReportPath, "Report");
                        }
                        else
                        {
                            runDesc.ReportLocation = Path.Combine(testPath, "Report");
                        }

                        if (Directory.Exists(runDesc.ReportLocation))
                        {
                            int lastIndex = runDesc.ReportLocation.IndexOf("\\");
                            var location  = runDesc.ReportLocation.Substring(0, lastIndex);
                            var name      = runDesc.ReportLocation.Substring(lastIndex + 1);
                            runDesc.ReportLocation = Helper.GetNextResFolder(location, name);
                            Console.WriteLine("Report location is:" + runDesc.ReportLocation);
                            //Directory.Delete(runDesc.ReportLocation, true);
                            Directory.CreateDirectory(runDesc.ReportLocation);
                        }
                    }


                    // Check for required Addins
                    LoadNeededAddins(testPath);

                    // set Mc connection and other mobile info into rack if neccesary
                    #region Mc connection and other mobile info

                    // Mc Address, username and password
                    if (!string.IsNullOrEmpty(_mcConnection.MobileHostAddress))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_HOST_ADDRESS, _mcConnection.MobileHostAddress);
                        if (!string.IsNullOrEmpty(_mcConnection.MobileHostPort))
                        {
                            _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_HOST_PORT, _mcConnection.MobileHostPort);
                        }
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobileUserName))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USER, _mcConnection.MobileUserName);
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobileTenantId))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_TENANT, _mcConnection.MobileTenantId);
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobilePassword))
                    {
                        string encriptedMcPassword = WinUserNativeMethods.ProtectBSTRToBase64(_mcConnection.MobilePassword);
                        if (encriptedMcPassword == null)
                        {
                            ConsoleWriter.WriteLine("ProtectBSTRToBase64 fail for mcPassword");
                            throw new Exception("ProtectBSTRToBase64 fail for mcPassword");
                        }
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PASSWORD, encriptedMcPassword);
                    }

                    // ssl and proxy info
                    _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USE_SSL, _mcConnection.MobileUseSSL);

                    if (_mcConnection.MobileUseProxy == 1)
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USE_PROXY, _mcConnection.MobileUseProxy);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_ADDRESS, _mcConnection.MobileProxySetting_Address);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_PORT, _mcConnection.MobileProxySetting_Port);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_AUTHENTICATION, _mcConnection.MobileProxySetting_Authentication);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_USERNAME, _mcConnection.MobileProxySetting_UserName);
                        string encriptedMcProxyPassword = WinUserNativeMethods.ProtectBSTRToBase64(_mcConnection.MobileProxySetting_Password);
                        if (encriptedMcProxyPassword == null)
                        {
                            ConsoleWriter.WriteLine("ProtectBSTRToBase64 fail for mc proxy Password");
                            throw new Exception("ProtectBSTRToBase64 fail for mc proxy Password");
                        }
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_PASSWORD, encriptedMcProxyPassword);
                    }

                    // Mc info (device, app, launch and terminate data)
                    if (!string.IsNullOrEmpty(_mobileInfo))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_INFO, _mobileInfo);
                    }

                    #endregion


                    if (!_qtpApplication.Launched)
                    {
                        if (_runCancelled())
                        {
                            QTPTestCleanup();
                            KillQtp();
                            runDesc.TestState = TestState.Error;
                            return(runDesc);
                        }
                        // Launch application after set Addins
                        _qtpApplication.Launch();
                        _qtpApplication.Visible = false;
                    }
                }
            }
            catch (Exception e)
            {
                errorReason            = Resources.QtpNotLaunchedError;
                runDesc.TestState      = TestState.Error;
                runDesc.ReportLocation = "";
                runDesc.ErrorDesc      = e.Message;
                return(runDesc);
            }

            if (_qtpApplication.Test != null && _qtpApplication.Test.Modified)
            {
                var message = Resources.QtpNotLaunchedError;
                errorReason       = message;
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            _qtpApplication.UseLicenseOfType(_useUFTLicense
                                                 ? tagUnifiedLicenseType.qtUnifiedFunctionalTesting
                                                 : tagUnifiedLicenseType.qtNonUnified);

            if (!HandleInputParameters(testPath, ref errorReason, testinf.GetParameterDictionaryForQTP(), testinf.DataTablePath))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            GuiTestRunResult guiTestRunResult = ExecuteQTPRun(runDesc);
            runDesc.ReportLocation = guiTestRunResult.ReportPath;

            if (!guiTestRunResult.IsSuccess)
            {
                runDesc.TestState = TestState.Error;
                return(runDesc);
            }

            if (!HandleOutputArguments(ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            QTPTestCleanup();


            return(runDesc);
        }
        /// <summary>
        /// runs the given test and returns resutls
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCanclled"></param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCanclled)
        {
            var            testPath = testinf.TestPath;
            TestRunResults runDesc  = new TestRunResults();

            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testPath);
            runDesc.ReportLocation = testPath;


            runDesc.TestPath  = testPath;
            runDesc.TestState = TestState.Unknown;

            _runCancelled = runCanclled;

            if (!Helper.IsQtpInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.GeneralQtpNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            string reason = string.Empty;

            if (!Helper.CanUftProcessStart(out reason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = reason;
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            try
            {
                ChangeDCOMSettingToInteractiveUser();
                var type = Type.GetTypeFromProgID("Quicktest.Application");

                lock (_lockObject)
                {
                    _qtpApplication = Activator.CreateInstance(type) as Application;

                    Version qtpVersion = Version.Parse(_qtpApplication.Version);
                    if (qtpVersion.Equals(new Version(11, 0)))
                    {
                        runDesc.ReportLocation = Path.Combine(testPath, "Report");
                        if (Directory.Exists(runDesc.ReportLocation))
                        {
                            Directory.Delete(runDesc.ReportLocation, true);
                            Directory.CreateDirectory(runDesc.ReportLocation);
                        }
                    }


                    // Check for required Addins
                    LoadNeededAddins(testPath);

                    if (!_qtpApplication.Launched)
                    {
                        if (_runCancelled())
                        {
                            QTPTestCleanup();
                            KillQtp();
                            runDesc.TestState = TestState.Error;
                            return(runDesc);
                        }
                        // Launch application after set Addins
                        _qtpApplication.Launch();
                        _qtpApplication.Visible = false;
                    }
                }
            }
            catch (Exception e)
            {
                errorReason            = Resources.QtpNotLaunchedError;
                runDesc.TestState      = TestState.Error;
                runDesc.ReportLocation = "";
                runDesc.ErrorDesc      = e.Message;
                return(runDesc);
            }

            if (_qtpApplication.Test != null && _qtpApplication.Test.Modified)
            {
                var message = Resources.QtpNotLaunchedError;
                errorReason       = message;
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            _qtpApplication.UseLicenseOfType(_useUFTLicense
                                                 ? tagUnifiedLicenseType.qtUnifiedFunctionalTesting
                                                 : tagUnifiedLicenseType.qtNonUnified);

            if (!HandleInputParameters(testPath, ref errorReason, testinf.GetParameterDictionaryForQTP()))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            GuiTestRunResult guiTestRunResult = ExecuteQTPRun(runDesc);

            runDesc.ReportLocation = guiTestRunResult.ReportPath;

            if (!guiTestRunResult.IsSuccess)
            {
                runDesc.TestState = TestState.Error;
                return(runDesc);
            }

            if (!HandleOutputArguments(ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            QTPTestCleanup();


            return(runDesc);
        }
示例#12
0
        private bool HandleInputParameters(string fileName, ref string errorReason, Dictionary <string, object> inputParams, TestInfo testInfo)
        {
            try
            {
                string path = fileName;

                if (_runCancelled())
                {
                    QTPTestCleanup();
                    KillQtp();
                    return(false);
                }

                _qtpApplication.Open(path, true, false);
                _qtpParamDefs  = _qtpApplication.Test.ParameterDefinitions;
                _qtpParameters = _qtpParamDefs.GetParameters();

                // handle all parameters (index starts with 1 !!!)
                for (int i = 1; i <= _qtpParamDefs.Count; i++)
                {
                    // input parameters
                    if (_qtpParamDefs[i].InOut == qtParameterDirection.qtParamDirIn)
                    {
                        string          paramName = _qtpParamDefs[i].Name;
                        qtParameterType type      = _qtpParamDefs[i].Type;

                        // if the caller supplies value for a parameter we set it
                        if (inputParams.ContainsKey(paramName))
                        {
                            // first verify that the type is correct
                            object paramValue = inputParams[paramName];
                            if (!VerifyParameterValueType(paramValue, type))
                            {
                                ConsoleWriter.WriteErrLine(string.Format("Illegal input parameter type (skipped). param: '{0}'. expected type: '{1}'. actual type: '{2}'", paramName, Enum.GetName(typeof(qtParameterType), type), paramValue.GetType()));
                            }
                            else
                            {
                                _qtpParameters[paramName].Value = paramValue;
                            }
                        }
                    }
                }

                // specify data table path
                if (testInfo.DataTablePath != null)
                {
                    _qtpApplication.Test.Settings.Resources.DataTablePath = testInfo.DataTablePath;
                    ConsoleWriter.WriteLine("Using external data table: " + testInfo.DataTablePath);
                }

                // specify iteration mode
                if (testInfo.IterationInfo != null)
                {
                    try
                    {
                        IterationInfo ii = testInfo.IterationInfo;
                        if (!IterationInfo.AvailableTypes.Contains(ii.IterationMode))
                        {
                            throw new ArgumentException(String.Format("Illegal iteration mode '{0}'. Available modes are : {1}", ii.IterationMode, string.Join(", ", IterationInfo.AvailableTypes)));
                        }

                        bool rangeMode = IterationInfo.RANGE_ITERATION_MODE.Equals(ii.IterationMode);
                        if (rangeMode)
                        {
                            int start = Int32.Parse(ii.StartIteration);
                            int end   = Int32.Parse(ii.EndIteration);

                            _qtpApplication.Test.Settings.Run.StartIteration = start;
                            _qtpApplication.Test.Settings.Run.EndIteration   = end;
                        }

                        _qtpApplication.Test.Settings.Run.IterationMode = testInfo.IterationInfo.IterationMode;

                        ConsoleWriter.WriteLine("Using iteration mode: " + testInfo.IterationInfo.IterationMode +
                                                (rangeMode ? " " + testInfo.IterationInfo.StartIteration + "-" + testInfo.IterationInfo.EndIteration : ""));
                    }
                    catch (Exception e)
                    {
                        String msg = "Failed to parse 'Iterations' element . Using default iteration settings. Error : " + e.Message;
                        ConsoleWriter.WriteLine(msg);
                    }
                }
            }
            catch (Exception)
            {
                errorReason = Resources.QtpRunError;
                return(false);
            }
            return(true);
        }
示例#13
0
        /// <summary>
        /// runs the given test and returns resutls
        /// </summary>
        /// <param name="testPath"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCanclled"></param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCanclled)
        {
            var            testPath = testinf.TestPath;
            TestRunResults runDesc  = new TestRunResults();

            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running test: " + testPath + " ...");

            runDesc.TestPath = testPath;

            // check if the report path has been defined
            if (!string.IsNullOrWhiteSpace(testinf.ReportPath))
            {
                runDesc.ReportLocation = Path.GetFullPath(testinf.ReportPath);
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is set explicitly: " + runDesc.ReportLocation);
            }
            else if (!String.IsNullOrEmpty(testinf.ReportBaseDirectory))
            {
                testinf.ReportBaseDirectory = Path.GetFullPath(testinf.ReportBaseDirectory);
                if (!Helper.TrySetTestReportPath(runDesc, testinf, ref errorReason))
                {
                    return(runDesc);
                }
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is generated under base directory: " + runDesc.ReportLocation);
            }
            else
            {
                // default report location is the next available folder under test path
                // for example, "path\to\tests\GUITest1\Report123", the name "Report123" will also be used as the report name
                string reportBasePath = Path.GetFullPath(testPath);
                string testReportPath = Path.Combine(reportBasePath, "Report" + DateTime.Now.ToString("ddMMyyyyHHmmssfff"));
                int    index          = 0;
                while (index < int.MaxValue)
                {
                    index++;
                    string dir = Path.Combine(reportBasePath, "Report" + index.ToString());
                    if (!Directory.Exists(dir))
                    {
                        testReportPath = dir;
                        break;
                    }
                }
                runDesc.ReportLocation = testReportPath;
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is automatically generated: " + runDesc.ReportLocation);
            }

            runDesc.TestState = TestState.Unknown;

            _runCancelled = runCanclled;

            if (!Helper.IsQtpInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.GeneralQtpNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            string reason = string.Empty;

            if (!Helper.CanUftProcessStart(out reason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = reason;
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            try
            {
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " " + Properties.Resources.LaunchingTestingTool);

                ChangeDCOMSettingToInteractiveUser();
                var type = Type.GetTypeFromProgID("Quicktest.Application");

                lock (_lockObject)
                {
                    // before creating qtp automation object which creates UFT process,
                    // try to check if the UFT process already exists
                    bool uftProcessExist = false;
                    bool isNewInstance;
                    using (Mutex m = new Mutex(true, "per_process_mutex_UFT", out isNewInstance))
                    {
                        if (!isNewInstance)
                        {
                            uftProcessExist = true;
                        }
                    }

                    // this will create UFT process
                    _qtpApplication = Activator.CreateInstance(type) as Application;

                    // try to get qtp status via qtp automation object
                    // this might fail if UFT is launched and waiting for user input on addins manage window
                    bool needKillUFTProcess = false;
                    // status: Not launched / Ready / Busy / Running / Recording / Waiting / Paused
                    string status = _qtpApplication.GetStatus();
                    switch (status)
                    {
                    case "Not launched":
                        if (uftProcessExist)
                        {
                            // UFT process exist but the status retrieved from qtp automation object is Not launched
                            // it means the UFT is launched but not shown the main window yet
                            // in which case it shall be considered as UFT is not used at all
                            // so here can kill the UFT process to continue
                            needKillUFTProcess = true;
                        }
                        break;

                    case "Ready":
                    case "Waiting":
                        // UFT is launched but not running or recording, shall be considered as UFT is not used
                        // no need kill UFT process here since the qtp automation object can work properly
                        break;

                    case "Busy":
                    case "Running":
                    case "Recording":
                    case "Paused":
                        // UFT is launched and somehow in use now, shouldn't kill UFT process
                        // here make the test fail
                        errorReason            = Resources.UFT_Running;
                        runDesc.TestState      = TestState.Error;
                        runDesc.ReportLocation = "";
                        runDesc.ErrorDesc      = errorReason;
                        return(runDesc);

                    default:
                        // by default, let the tool run test, the behavior might be unexpected
                        break;
                    }

                    if (needKillUFTProcess)
                    {
                        Process[] procs = Process.GetProcessesByName("uft");
                        if (procs != null)
                        {
                            foreach (Process proc in procs)
                            {
                                proc.Kill();
                            }
                        }
                    }

                    Version qtpVersion = Version.Parse(_qtpApplication.Version);
                    if (qtpVersion.Equals(new Version(11, 0)))
                    {
                        // use the defined report path if provided
                        if (!string.IsNullOrWhiteSpace(testinf.ReportPath))
                        {
                            runDesc.ReportLocation = Path.Combine(testinf.ReportPath, "Report");
                        }
                        else if (!string.IsNullOrWhiteSpace(testinf.ReportBaseDirectory))
                        {
                            runDesc.ReportLocation = Path.Combine(testinf.ReportBaseDirectory, "Report");
                        }
                        else
                        {
                            runDesc.ReportLocation = Path.Combine(testPath, "Report");
                        }

                        if (Directory.Exists(runDesc.ReportLocation))
                        {
                            int lastIndex = runDesc.ReportLocation.IndexOf("\\");
                            var location  = runDesc.ReportLocation.Substring(0, lastIndex);
                            var name      = runDesc.ReportLocation.Substring(lastIndex + 1);
                            runDesc.ReportLocation = Helper.GetNextResFolder(location, name);
                            Console.WriteLine("Report location is:" + runDesc.ReportLocation);
                            Directory.CreateDirectory(runDesc.ReportLocation);
                        }
                    }


                    // Check for required Addins
                    LoadNeededAddins(testPath);

                    // set Mc connection and other mobile info into rack if neccesary
                    #region Mc connection and other mobile info

                    // Mc Address, username and password
                    if (!string.IsNullOrEmpty(_mcConnection.MobileHostAddress))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_HOST_ADDRESS, _mcConnection.MobileHostAddress);
                        if (!string.IsNullOrEmpty(_mcConnection.MobileHostPort))
                        {
                            _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_HOST_PORT, _mcConnection.MobileHostPort);
                        }
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobileUserName))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USER, _mcConnection.MobileUserName);
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobileTenantId))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_TENANT, _mcConnection.MobileTenantId);
                    }

                    if (!string.IsNullOrEmpty(_mcConnection.MobilePassword))
                    {
                        string encriptedMcPassword = WinUserNativeMethods.ProtectBSTRToBase64(_mcConnection.MobilePassword);
                        if (encriptedMcPassword == null)
                        {
                            ConsoleWriter.WriteLine("ProtectBSTRToBase64 fail for mcPassword");
                            throw new Exception("ProtectBSTRToBase64 fail for mcPassword");
                        }
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PASSWORD, encriptedMcPassword);
                    }

                    // ssl and proxy info
                    _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USE_SSL, _mcConnection.MobileUseSSL);

                    if (_mcConnection.MobileUseProxy == 1)
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_USE_PROXY, _mcConnection.MobileUseProxy);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_ADDRESS, _mcConnection.MobileProxySetting_Address);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_PORT, _mcConnection.MobileProxySetting_Port);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_AUTHENTICATION, _mcConnection.MobileProxySetting_Authentication);
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_USERNAME, _mcConnection.MobileProxySetting_UserName);
                        string encriptedMcProxyPassword = WinUserNativeMethods.ProtectBSTRToBase64(_mcConnection.MobileProxySetting_Password);
                        if (encriptedMcProxyPassword == null)
                        {
                            ConsoleWriter.WriteLine("ProtectBSTRToBase64 fail for mc proxy Password");
                            throw new Exception("ProtectBSTRToBase64 fail for mc proxy Password");
                        }
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_PROXY_SETTING_PASSWORD, encriptedMcProxyPassword);
                    }

                    // Mc info (device, app, launch and terminate data)
                    if (!string.IsNullOrEmpty(_mobileInfo))
                    {
                        _qtpApplication.TDPierToTulip.SetTestOptionsVal(MOBILE_INFO, _mobileInfo);
                    }

                    #endregion


                    if (!_qtpApplication.Launched)
                    {
                        if (_runCancelled())
                        {
                            QTPTestCleanup();
                            KillQtp();
                            runDesc.TestState = TestState.Error;
                            return(runDesc);
                        }
                        // Launch application after set Addins
                        _qtpApplication.Launch();
                        _qtpApplication.Visible = false;
                    }
                }
            }
            catch (Exception e)
            {
                string errorMsg        = e.Message;
                string errorStacktrace = string.IsNullOrWhiteSpace(e.StackTrace) ? string.Empty : e.StackTrace;
                errorReason = Resources.QtpNotLaunchedError + "\n" + string.Format(Resources.ExceptionDetails, errorMsg, errorStacktrace);
                if (e is SystemException)
                {
                    errorReason += "\n" + Resources.QtpNotLaunchedError_PossibleSolution_RegModellib;
                }

                runDesc.TestState      = TestState.Error;
                runDesc.ReportLocation = "";
                runDesc.ErrorDesc      = errorReason;
                return(runDesc);
            }

            if (_qtpApplication.Test != null && _qtpApplication.Test.Modified)
            {
                var message = Resources.QtpNotLaunchedError;
                errorReason       = message;
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            _qtpApplication.UseLicenseOfType(_useUFTLicense
                                                 ? tagUnifiedLicenseType.qtUnifiedFunctionalTesting
                                                 : tagUnifiedLicenseType.qtNonUnified);

            Dictionary <string, object> paramList = testinf.GetParameterDictionaryForQTP();

            if (!HandleInputParameters(testPath, ref errorReason, testinf.GetParameterDictionaryForQTP(), testinf))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            GuiTestRunResult guiTestRunResult = ExecuteQTPRun(runDesc);

            // consider backward compatibility, here move the report folder one outside
            // that is, after test run, the report file might be at "path\to\tests\GUITest1\Report123\Report\run_results.html"
            // here move the last directory "Report" one level outside, which is, "path\to\tests\GUITest1\Report123\run_results.html"
            // steps:
            //   1. move directory "path\to\tests\GUITest1\Report123" to "path\to\tests\GUITest1\tmp_ddMMyyyyHHmmssfff"
            string guiTestReportPath = guiTestRunResult.ReportPath;                                                      // guiTestReportPath: path\to\tests\GUITest1\Report123\Report
            string targetReportDir   = Path.GetDirectoryName(guiTestReportPath);                                         // reportDir: path\to\tests\GUITest1\Report123
            string reportBaseDir     = Path.GetDirectoryName(targetReportDir);                                           // reportBaseDir: path\to\tests\GUITest1
            string tmpDir            = Path.Combine(reportBaseDir, "tmp_" + DateTime.Now.ToString("ddMMyyyyHHmmssfff")); // tmpDir: path\to\tests\GUITest1\tmp_ddMMyyyyHHmmssfff
            //   1.a) directory move may fail because UFT might still be writting report files, need retry
            const int maxMoveDirRetry = 30;
            int       moveDirRetry    = 0;
            bool      dirMoved        = false;
            do
            {
                try
                {
                    Directory.Move(targetReportDir, tmpDir);
                    dirMoved = true;
                    break;
                }
                catch (IOException)
                {
                    moveDirRetry++;
                    if (moveDirRetry == 1)
                    {
                        ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) +
                                                string.Format(" Report is not ready yet, wait up to {0} seconds ...", maxMoveDirRetry));
                    }
                    Thread.Sleep(1000);
                }
            } while (moveDirRetry < maxMoveDirRetry);

            if (dirMoved)
            {
                // 2. move directory "path\to\tests\GUITest1\tmp_ddMMyyyyHHmmssfff\Report" to "path\to\tests\GUITest1\Report123"
                string tmpReportDir = Path.Combine(tmpDir, "Report");           // tmpReportDir: path\to\tests\GUITest1\tmp_ddMMyyyyHHmmssfff\Report
                Directory.Move(tmpReportDir, targetReportDir);
                // 3. delete the temp directory "path\to\test1\tmp_ddMMyyyyHHmmssfff"
                Directory.Delete(tmpDir, true);
                runDesc.ReportLocation = targetReportDir;
            }
            else
            {
                runDesc.ReportLocation = guiTestReportPath;
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) +
                                        " Warning: Report folder is still in use, leave it in: " + guiTestReportPath);
            }

            if (!guiTestRunResult.IsSuccess)
            {
                runDesc.TestState = TestState.Error;
                return(runDesc);
            }

            if (!HandleOutputArguments(ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
                return(runDesc);
            }

            QTPTestCleanup();


            return(runDesc);
        }
示例#14
0
        /// <summary>
        /// Set the error for a test when the report path is invalid.
        /// </summary>
        /// <param name="runResults"> The test run results </param>
        /// <param name="errorReason"> The error reason </param>
        /// <param name="testInfo"> The test informatio </param>
        public static void SetTestReportPathError(TestRunResults runResults, ref string errorReason, TestInfo testInfo)
        {
            // Invalid path was provided, return useful description
            errorReason = string.Format(Resources.InvalidReportPath, runResults.ReportLocation);

            // since the report path is invalid, the test should fail
            runResults.TestState = TestState.Error;
            runResults.ErrorDesc = errorReason;

            // output the error for the current test run
            ConsoleWriter.WriteErrLine(runResults.ErrorDesc);

            // include the error in the summary
            ConsoleWriter.ErrorSummaryLines.Add(runResults.ErrorDesc);

            // provide the appropriate exit code for the launcher
            Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
        }
 private bool IsCleanupTest(TestInfo test)
 {
     return(IsCleanupTestDefined() && test.TestPath.Equals(_tests[0].TestPath));
 }
        /// <summary>
        /// runs the given test
        /// </summary>
        /// <param name="testinf"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCancelled">cancellation delegate, holds the function that checks cancellation</param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCancelled)
        {
            TestRunResults runDesc = new TestRunResults();
            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testinf.TestPath);

            runDesc.ReportLocation = Helper.CreateTempDir();
            runDesc.ErrorDesc = errorReason;
            runDesc.TestPath = testinf.TestPath;
            runDesc.TestState = TestState.Unknown;
            if (!Helper.IsServiceTestInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.LauncherStNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return runDesc;
            }

            _runCancelled = runCancelled;
            if (!_stCanRun)
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                return runDesc;
            }
            string fileName = Path.Combine(_stExecuterPath, STRunnerName);

            if (!File.Exists(fileName))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                ConsoleWriter.WriteErrLine(Resources.STExecuterNotFound);
                return runDesc;
            }

            //write the input parameter xml file for the API test
            string paramFileName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 10);
            string tempPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestParams");
            Directory.CreateDirectory(tempPath);
            string paramsFilePath = Path.Combine(tempPath, "params" + paramFileName + ".xml");
            string paramFileContent = testinf.GenerateAPITestXmlForTest();

            string argumentString = "";
            if (!string.IsNullOrWhiteSpace(paramFileContent))
            {
                File.WriteAllText(paramsFilePath, paramFileContent);
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\" {4} \"{5}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation, STRunnerInputParamsArg, paramsFilePath);
            }
            else
            {
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation);
            }

            Stopwatch s = Stopwatch.StartNew();
            runDesc.TestState = TestState.Running;

            if (!ExecuteProcess(fileName,
                                argumentString,
                                ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
            }
            else
            {
                runDesc.ReportLocation = Path.Combine(runDesc.ReportLocation, "Report");
                if (!File.Exists(Path.Combine(runDesc.ReportLocation, "Results.xml")))
                {
                    runDesc.TestState = TestState.Error;
                    runDesc.ErrorDesc = "No Results.xml file found";
                }
            }
            //File.Delete(paramsFilePath);
            runDesc.Runtime = s.Elapsed;
            return runDesc;
        }
 private bool IsTestPlaceholder(TestInfo test)
 {
     return(test.TestPath.Equals("-"));
 }
        /// <summary>
        /// creates instance of the runner given a source.
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="timeout"></param>
        /// <param name="backgroundWorker"></param>
        /// <param name="useUFTLicense"></param>
        public FileSystemTestsRunner(List<string> sources,
            TimeSpan timeout,
            int ControllerPollingInterval,
            TimeSpan perScenarioTimeOutMinutes,
            List<string> ignoreErrorStrings,
            Dictionary<string, string> jenkinsEnvVariables,
            string fsAppParamName,
            string appIdentifier,
            bool useUFTLicense = false
            )
        {
            _jenkinsEnvVariables = jenkinsEnvVariables;
            //search if we have any testing tools installed
            if (!Helper.IsTestingToolsInstalled(TestStorageType.FileSystem))
            {
                ConsoleWriter.WriteErrLine(string.Format(Resources.FileSystemTestsRunner_No_HP_testing_tool_is_installed_on, System.Environment.MachineName));
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            _timeout = timeout;
            ConsoleWriter.WriteLine("FileSystemTestRunner timeout is " + _timeout );
            _stopwatch = Stopwatch.StartNew();

            _pollingInterval = ControllerPollingInterval;
            _perScenarioTimeOutMinutes = perScenarioTimeOutMinutes;
            _ignoreErrorStrings = ignoreErrorStrings;

            _useUFTLicense = useUFTLicense;
            _tests = new List<TestInfo>();

            //go over all sources, and create a list of all tests
            foreach (string source in sources)
            {
                List<TestInfo> testGroup = new List<TestInfo>();
                try
                {
                    //--handle directories which contain test subdirectories (recursively)
                    if (Helper.IsDirectory(source))
                    {

                        var testsLocations = Helper.GetTestsLocations(source);
                        foreach (var loc in testsLocations)
                        {
                            var test = new TestInfo(loc, loc, source);
                            testGroup.Add(test);
                        }
                    }
                    //--handle mtb files (which contain links to tests)
                    else
                    //file might be LoadRunner scenario or
                    //mtb file (which contain links to tests)
                    //other files are dropped
                    {
                        testGroup = new List<TestInfo>();
                        FileInfo fi = new FileInfo(source);
                        if (fi.Extension == Helper.LoadRunnerFileExtention)
                            testGroup.Add(new TestInfo(source, source, source));
                        else if (fi.Extension == ".mtb")
                        //if (source.TrimEnd().EndsWith(".mtb", StringComparison.CurrentCultureIgnoreCase))
                        {
                            MtbManager manager = new MtbManager();
                            var paths = manager.Parse(source);
                            foreach (var p in paths)
                            {
                                testGroup.Add(new TestInfo(p, p, source));
                            }
                        }
                        else if (fi.Extension == ".mtbx")
                        //if (source.TrimEnd().EndsWith(".mtb", StringComparison.CurrentCultureIgnoreCase))
                        {
                            testGroup = MtbxManager.Parse(source, _jenkinsEnvVariables, source);
                            if (!string.IsNullOrEmpty(fsAppParamName) && !string.IsNullOrEmpty(appIdentifier))
                            {
                                var testParam = new TestParameterInfo() { Name = fsAppParamName, Type = "string", Value = appIdentifier };
                                foreach(TestInfo testInfo in testGroup)
                                {
                                    testInfo.ParameterList.Add(testParam);
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    testGroup = new List<TestInfo>();
                }

                //--handle single test dir, add it with no group
                if (testGroup.Count == 1)
                {
                    testGroup[0].TestGroup = "<None>";
                }

                _tests.AddRange(testGroup);
            }

            if (_tests == null || _tests.Count == 0)
            {
                ConsoleWriter.WriteLine(Resources.FsRunnerNoValidTests);
                Environment.Exit((int)Launcher.ExitCodeEnum.Failed);
            }

            ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerTestsFound, _tests.Count));
            _tests.ForEach(t => ConsoleWriter.WriteLine("" + t.TestName));
            ConsoleWriter.WriteLine(Resources.GeneralDoubleSeperator);
        }
示例#19
0
        /// <summary>
        /// runs the given test
        /// </summary>
        /// <param name="testinf"></param>
        /// <param name="errorReason"></param>
        /// <param name="runCancelled">cancellation delegate, holds the function that checks cancellation</param>
        /// <returns></returns>
        public TestRunResults RunTest(TestInfo testinf, ref string errorReason, RunCancelledDelegate runCancelled)
        {
            TestRunResults runDesc = new TestRunResults();

            ConsoleWriter.ActiveTestRun = runDesc;
            ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Running: " + testinf.TestPath);

            runDesc.TestPath = testinf.TestPath;

            // check if the report path has been defined
            if (!string.IsNullOrWhiteSpace(testinf.ReportPath))
            {
                runDesc.ReportLocation = testinf.ReportPath;
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is set explicitly: " + runDesc.ReportLocation);
            }
            else if (!String.IsNullOrEmpty(testinf.ReportBaseDirectory))
            {
                if (!Helper.TrySetTestReportPath(runDesc, testinf, ref errorReason))
                {
                    return(runDesc);
                }
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is generated under base directory: " + runDesc.ReportLocation);
            }
            else
            {
                // default report location is the next available folder under test path
                // for example, "path\to\tests\APITest\Report123", the name "Report123" will also be used as the report name
                string reportBasePath = testinf.TestPath;
                string testReportPath = Path.Combine(reportBasePath, "Report" + DateTime.Now.ToString("ddMMyyyyHHmmssfff"));
                int    index          = 0;
                while (index < int.MaxValue)
                {
                    index++;
                    string dir = Path.Combine(reportBasePath, "Report" + index.ToString());
                    if (!Directory.Exists(dir))
                    {
                        testReportPath = dir;
                        break;
                    }
                }
                runDesc.ReportLocation = testReportPath;
                ConsoleWriter.WriteLine(DateTime.Now.ToString(Launcher.DateFormat) + " Report path is automatically generated: " + runDesc.ReportLocation);
            }

            runDesc.ErrorDesc = errorReason;
            runDesc.TestState = TestState.Unknown;
            if (!Helper.IsServiceTestInstalled())
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = string.Format(Resources.LauncherStNotInstalled, System.Environment.MachineName);
                ConsoleWriter.WriteErrLine(runDesc.ErrorDesc);
                Environment.ExitCode = (int)Launcher.ExitCodeEnum.Failed;
                return(runDesc);
            }

            _runCancelled = runCancelled;
            if (!_stCanRun)
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                return(runDesc);
            }
            string fileName = Path.Combine(_stExecuterPath, STRunnerName);

            if (!File.Exists(fileName))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = Resources.STExecuterNotFound;
                ConsoleWriter.WriteErrLine(Resources.STExecuterNotFound);
                return(runDesc);
            }

            //write the input parameter xml file for the API test
            string paramFileName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 10);
            string tempPath      = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestParams");

            Directory.CreateDirectory(tempPath);
            string paramsFilePath   = Path.Combine(tempPath, "params" + paramFileName + ".xml");
            string paramFileContent = testinf.GenerateAPITestXmlForTest();

            string argumentString = "";

            if (!string.IsNullOrWhiteSpace(paramFileContent))
            {
                File.WriteAllText(paramsFilePath, paramFileContent);
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\" {4} \"{5}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation, STRunnerInputParamsArg, paramsFilePath);
            }
            else
            {
                argumentString = String.Format("{0} \"{1}\" {2} \"{3}\"", STRunnerTestArg, testinf.TestPath, STRunnerReportArg, runDesc.ReportLocation);
            }

            Stopwatch s = Stopwatch.StartNew();

            runDesc.TestState = TestState.Running;

            if (!ExecuteProcess(fileName,
                                argumentString,
                                ref errorReason))
            {
                runDesc.TestState = TestState.Error;
                runDesc.ErrorDesc = errorReason;
            }
            else
            {
                // consider backward compatibility, here move the report folder one outside
                // that is, after test run, the report file might be at "path\to\tests\APITest1\Report123\Report\run_results.html"
                // here move the last directory "Report" one level outside, which is, "path\to\tests\APITest1\Report123\run_results.html"
                string apiTestReportPath = Path.Combine(runDesc.ReportLocation, "Report");                                   // apiTestReportPath: path\to\tests\APITest1\Report123\Report
                string targetReportDir   = Path.GetDirectoryName(apiTestReportPath);                                         // reportDir: path\to\tests\APITest1\Report123
                string reportBaseDir     = Path.GetDirectoryName(targetReportDir);                                           // reportBaseDir: path\to\tests\APITest1
                string tmpDir            = Path.Combine(reportBaseDir, "tmp_" + DateTime.Now.ToString("ddMMyyyyHHmmssfff")); // tmpDir: path\to\tests\APITest1\tmp_ddMMyyyyHHmmssfff
                string tmpReportDir      = Path.Combine(tmpDir, "Report");                                                   // tmpReportDir: path\to\tests\APITest1\tmp_ddMMyyyyHHmmssfff\Report

                // since some files might not be closed yet, move the report folder might fail
                // so here will try a few times to move folder and let it as is (not moved) if still failed after several retry
                bool   moveSuccess   = false;
                string lastMoveError = string.Empty;
                int    retry         = 10;
                while (retry >= 0)
                {
                    try
                    {
                        // steps:
                        //   1. move directory "path\to\tests\APITest1\Report123" to "path\to\tests\APITest1\tmp_ddMMyyyyHHmmssfff"
                        Directory.Move(targetReportDir, tmpDir);
                        //   2. move directory "path\to\tests\APITest1\tmp_ddMMyyyyHHmmssfff\Report" to "path\to\tests\APITest1\Report123"
                        Directory.Move(tmpReportDir, targetReportDir);
                        //   3. delete empty directory "path\to\test1\tmp_ddMMyyyyHHmmssfff"
                        Directory.Delete(tmpDir, true);
                        //   4. update report location
                        runDesc.ReportLocation = targetReportDir;
                        moveSuccess            = true;
                        break;
                    }
                    catch (Exception ex)
                    {
                        lastMoveError = ex.Message;
                        retry--;
                        System.Threading.Thread.Sleep(500);
                    }
                }
                if (!moveSuccess)
                {
                    ConsoleWriter.WriteLine("Warning: Failed to change the report folder structure. " + lastMoveError);
                }

                if (!File.Exists(Path.Combine(runDesc.ReportLocation, "Results.xml")) && !File.Exists(Path.Combine(runDesc.ReportLocation, "run_results.html")))
                {
                    runDesc.TestState = TestState.Error;
                    runDesc.ErrorDesc = "No Results.xml or run_results.html file found";
                }
            }
            //File.Delete(paramsFilePath);
            runDesc.Runtime = s.Elapsed;
            return(runDesc);
        }