private GuiTestRunResult HandleExecutionCanceled(TestRunResults testResults)
        {
            ConsoleWriter.WriteLine("Execution Canceled!");
            GuiTestRunResult result = new GuiTestRunResult();

            testResults.TestState = TestState.Error;
            testResults.ErrorDesc = Resources.GeneralTestCanceled;
            ConsoleWriter.WriteLine(Resources.GeneralTestCanceled);
            Launcher.ExitCode = Launcher.ExitCodeEnum.Aborted;
            result.IsSuccess  = false;
            return(result);
        }
        /// <summary>
        /// runs the given test QTP and returns results
        /// </summary>
        /// <param name="testResults">the test results object containing test info and also receiving run results</param>
        /// <returns></returns>
        private GuiTestRunResult ExecuteQTPRun(TestRunResults testResults)
        {
            RunResultsOptions options = CreateRunResultOptions(testResults);

            if (_runCancelled())
            {
                return(HandleExecutionCanceled(testResults));
            }

            try
            {
                ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerRunningTest, testResults.TestPath));
                _qtpApplication.Options.Run.RunMode = _uftRunMode;
                _qtpApplication.Test.Run(options, false, _qtpParameters);

                WaitForTestExecutionComplete(testResults);
                if (_runCancelled())
                {
                    CloseTARobot();
                    return(HandleExecutionCanceled(testResults));
                }

                return(AnalyzeLastRunResults(testResults));
            }
            catch (Exception e2)
            {
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e2.Message, e2.StackTrace));
                CloseTARobot();

                GuiTestRunResult result = new GuiTestRunResult();
                result.ReportPath          = options.ResultsLocation;
                testResults.TestState      = TestState.Error;
                testResults.ReportLocation = result.ReportPath;

                if (String.IsNullOrEmpty(testResults.ErrorDesc))
                {
                    testResults.ErrorDesc = Resources.QtpRunError;
                }

                result.IsSuccess = false;
                return(result);
            }
        }
        private GuiTestRunResult AnalyzeLastRunResults(TestRunResults testResults)
        {
            GuiTestRunResult result = new GuiTestRunResult {
                IsSuccess = true
            };

            result.ReportPath = Path.Combine(testResults.ReportLocation, "Report");
            string lastError = _qtpApplication.Test.LastRunResults.LastError;

            //read the lastError
            if (!String.IsNullOrEmpty(lastError))
            {
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = lastError;
            }

            // the way to check the logical success of the target QTP test is: app.Test.LastRunResults.Status == "Passed".
            if (_qtpApplication.Test.LastRunResults.Status.Equals("Passed"))
            {
                testResults.TestState = TestState.Passed;
            }
            else if (_qtpApplication.Test.LastRunResults.Status.Equals("Warning"))
            {
                testResults.TestState   = TestState.Passed;
                testResults.HasWarnings = true;

                if (Launcher.ExitCode != Launcher.ExitCodeEnum.Failed && Launcher.ExitCode != Launcher.ExitCodeEnum.Aborted)
                {
                    Launcher.ExitCode = Launcher.ExitCodeEnum.Unstable;
                }
            }
            else
            {
                testResults.TestState   = TestState.Failed;
                testResults.FailureDesc = "Test failed";

                Launcher.ExitCode = Launcher.ExitCodeEnum.Failed;
            }

            return(result);
        }
예제 #4
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: " + 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);
        }
예제 #5
0
        /// <summary>
        /// runs the given test QTP and returns results
        /// </summary>
        /// <param name="testResults">the test results object containing test info and also receiving run results</param>
        /// <returns></returns>
        private GuiTestRunResult ExecuteQTPRun(TestRunResults testResults)
        {
            GuiTestRunResult result = new GuiTestRunResult {
                IsSuccess = true
            };

            try
            {
                Type runResultsOptionstype = Type.GetTypeFromProgID("QuickTest.RunResultsOptions");
                var  options = (RunResultsOptions)Activator.CreateInstance(runResultsOptionstype);
                options.ResultsLocation             = testResults.ReportLocation;
                _qtpApplication.Options.Run.RunMode = "Fast";

                //Check for cancel before executing
                if (_runCancelled())
                {
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = Resources.GeneralTestCanceled;
                    ConsoleWriter.WriteLine(Resources.GeneralTestCanceled);
                    result.IsSuccess = false;
                    return(result);
                }
                ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerRunningTest, testResults.TestPath));

                _qtpApplication.Test.Run(options, false, _qtpParameters);

                result.ReportPath = Path.Combine(testResults.ReportLocation, "Report");
                int slept = 0;
                while ((slept < 20000 && _qtpApplication.GetStatus().Equals("Ready")) || _qtpApplication.GetStatus().Equals("Waiting"))
                {
                    Thread.Sleep(50);
                    slept += 50;
                }


                while (!_runCancelled() && (_qtpApplication.GetStatus().Equals("Running") || _qtpApplication.GetStatus().Equals("Busy")))
                {
                    Thread.Sleep(200);
                    if (_timeLeftUntilTimeout - _stopwatch.Elapsed <= TimeSpan.Zero)
                    {
                        _qtpApplication.Test.Stop();
                        testResults.TestState = TestState.Error;
                        testResults.ErrorDesc = Resources.GeneralTimeoutExpired;
                        ConsoleWriter.WriteLine(Resources.GeneralTimeoutExpired);

                        result.IsSuccess = false;
                        return(result);
                    }
                }

                if (_runCancelled())
                {
                    QTPTestCleanup();
                    KillQtp();
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = Resources.GeneralTestCanceled;
                    ConsoleWriter.WriteLine(Resources.GeneralTestCanceled);
                    Launcher.ExitCode = Launcher.ExitCodeEnum.Aborted;
                    result.IsSuccess  = false;
                    return(result);
                }
                string lastError = _qtpApplication.Test.LastRunResults.LastError;

                //read the lastError
                if (!String.IsNullOrEmpty(lastError))
                {
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = lastError;
                }

                // the way to check the logical success of the target QTP test is: app.Test.LastRunResults.Status == "Passed".
                if (_qtpApplication.Test.LastRunResults.Status.Equals("Passed"))
                {
                    testResults.TestState = TestState.Passed;
                }
                else if (_qtpApplication.Test.LastRunResults.Status.Equals("Warning"))
                {
                    testResults.TestState   = TestState.Passed;
                    testResults.HasWarnings = true;

                    if (Launcher.ExitCode != Launcher.ExitCodeEnum.Failed && Launcher.ExitCode != Launcher.ExitCodeEnum.Aborted)
                    {
                        Launcher.ExitCode = Launcher.ExitCodeEnum.Unstable;
                    }
                }
                else
                {
                    testResults.TestState   = TestState.Failed;
                    testResults.FailureDesc = "Test failed";

                    Launcher.ExitCode = Launcher.ExitCodeEnum.Failed;
                }
            }
            catch (NullReferenceException e)
            {
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e.Message, e.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return(result);
            }
            catch (SystemException e)
            {
                KillQtp();
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e.Message, e.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return(result);
            }
            catch (Exception e2)
            {
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e2.Message, e2.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return(result);
            }


            return(result);
        }
예제 #6
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: " + 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);

                    // 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.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()))
            {
                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 QTP and returns results
        /// </summary>
        /// <param name="testResults">the test results object containing test info and also receiving run results</param>
        /// <returns></returns>
        private GuiTestRunResult ExecuteQTPRun(TestRunResults testResults)
        {
            GuiTestRunResult result = new GuiTestRunResult { IsSuccess = true };
            try
            {
                Type runResultsOptionstype = Type.GetTypeFromProgID("QuickTest.RunResultsOptions");
                var options = (RunResultsOptions)Activator.CreateInstance(runResultsOptionstype);
                options.ResultsLocation = testResults.ReportLocation;
                _qtpApplication.Options.Run.RunMode = "Fast";

                //Check for cancel before executing
                if (_runCancelled())
                {
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = Resources.GeneralTestCanceled;
                    ConsoleWriter.WriteLine(Resources.GeneralTestCanceled);
                    result.IsSuccess = false;
                    return result;
                }
                ConsoleWriter.WriteLine(string.Format(Resources.FsRunnerRunningTest, testResults.TestPath));

                _qtpApplication.Test.Run(options, false, _qtpParameters);

                result.ReportPath = Path.Combine(testResults.ReportLocation, "Report");
                int slept = 0;
                while (slept < 20000 && _qtpApplication.GetStatus().Equals("Ready"))
                {
                    Thread.Sleep(50);
                    slept += 50;
                }

                while (!_runCancelled() && (_qtpApplication.GetStatus().Equals("Running") || _qtpApplication.GetStatus().Equals("Busy")))
                {
                    Thread.Sleep(200);
                    if (_timeLeftUntilTimeout - _stopwatch.Elapsed <= TimeSpan.Zero)
                    {
                        _qtpApplication.Test.Stop();
                        testResults.TestState = TestState.Error;
                        testResults.ErrorDesc = Resources.GeneralTimeoutExpired;
                        ConsoleWriter.WriteLine(Resources.GeneralTimeoutExpired);

                        result.IsSuccess = false;
                        return result;
                    }
                }

                if (_runCancelled())
                {
                    QTPTestCleanup();
                    KillQtp();
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = Resources.GeneralTestCanceled;
                    ConsoleWriter.WriteLine(Resources.GeneralTestCanceled);
                    Launcher.ExitCode = Launcher.ExitCodeEnum.Aborted;
                    result.IsSuccess = false;
                    return result;
                }
                string lastError = _qtpApplication.Test.LastRunResults.LastError;

                //read the lastError
                if (!String.IsNullOrEmpty(lastError))
                {
                    testResults.TestState = TestState.Error;
                    testResults.ErrorDesc = lastError;
                }

                // the way to check the logical success of the target QTP test is: app.Test.LastRunResults.Status == "Passed".
                if (_qtpApplication.Test.LastRunResults.Status.Equals("Passed"))
                {
                    testResults.TestState = TestState.Passed;

                }
                else if (_qtpApplication.Test.LastRunResults.Status.Equals("Warning"))
                {
                    testResults.TestState = TestState.Passed;
                    testResults.HasWarnings = true;

                    if (Launcher.ExitCode != Launcher.ExitCodeEnum.Failed && Launcher.ExitCode != Launcher.ExitCodeEnum.Aborted)
                        Launcher.ExitCode = Launcher.ExitCodeEnum.Unstable;
                }
                else
                {
                    testResults.TestState = TestState.Failed;
                    testResults.FailureDesc = "Test failed";

                    Launcher.ExitCode = Launcher.ExitCodeEnum.Failed;
                }
            }
            catch (NullReferenceException e)
            {
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e.Message, e.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return result;
            }
            catch (SystemException e)
            {
                KillQtp();
                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e.Message, e.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return result;
            }
            catch (Exception e2)
            {

                ConsoleWriter.WriteLine(string.Format(Resources.GeneralErrorWithStack, e2.Message, e2.StackTrace));
                testResults.TestState = TestState.Error;
                testResults.ErrorDesc = Resources.QtpRunError;

                result.IsSuccess = false;
                return result;
            }

            return result;
        }
예제 #8
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);
        }