jenkins - 当从 jenkins 调用时,无法在 testcomplete 中运行自动化项目

标签 jenkins continuous-integration jenkins-plugins testcomplete

当来自 jenkins 的调用时,无法在 testcomplete 中运行自动化项目。

在我们的持续集成部分,该项目使用testcomplete实现自动化,并在bat文件的帮助下通过jenkins进行调用。bat文件中的脚本是

"C:\Program Files\Automated QA\TestComplete 7\Bin\TestComplete.exe "  "D:\Test Complete7 Projects\ProjectInput_AllSamples\ProjecInputs.pjs" /r /p:Samples /rt:Main "iexplore" /e

它将打开 testcomplete 和 iexplorer ,但它不会填充数据(自动化)。 当我们直接调用bat文件而不使用jenkins时,它可以正常工作。有什么解决方案

最佳答案

根据您的描述,这听起来像是 Windows 中的某些内容阻止您让测试应用程序正常工作。事实上,第二个用户可能会出现问题,但我无法确认这一点,因为我找不到任何关于它在 Windows XP 中如何工作的明确解释。我非常确定这不会在 Windows Vista、7、8 或服务器计算机上运行,​​因为 changes in architecture

听起来最好的解决方案是确保自动化 UI 测试由交互式用户启动。当我尝试将自动化测试添加到我们的构建中时,我​​们在 Windows XP SP2 虚拟机上使用了 TestComplete 7。为了作为交互式用户开始我们的测试,我们:

  • 在 Windows 启动时让用户登录,这样总会有一个交互式用户,这意味着存在一个可以访问键盘/鼠标的实际桌面 session 。我似乎记得(但目前找不到任何链接),如果没有交互式用户,就没有可以访问键盘/鼠标的事件桌面。
  • 我们编写了一个小应用程序,它将在交互式用户登录时启动。该应用程序将查看特定文件,当该文件更改/创建时,它将读取该文件并启动应用程序。这个应用程序的代码看起来有点像这样:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ApplicationStarter
    {
        class Program
        {
            // The string used to indicate that the application should quit.
            private const string ExitString = "exit";
    
            // The path which is being watched for changes.
            private static string s_LoadFilePath;
    
            static void Main(string[] args)
            {
                try
                {
                    {
                        Debug.Assert(
                            args != null, 
                            "The arguments array should not be null.");
                        Debug.Assert(
                            args.Length == 1, 
                            "There should only be one argument.");
                    }
    
                    s_LoadFilePath = args[0];
                    {
                        Console.WriteLine(
                            string.Format(
                                CultureInfo.InvariantCulture, 
                                "Watching: {0}", 
                                s_LoadFilePath));
                    }
    
                    if (File.Exists(s_LoadFilePath))
                    {
                        RunApplication(s_LoadFilePath);
                    }
    
                    using (var watcher = new FileSystemWatcher())
                    {
                        watcher.IncludeSubdirectories = false;
                        watcher.NotifyFilter =
                           NotifyFilters.LastAccess 
                           | NotifyFilters.LastWrite 
                           | NotifyFilters.FileName 
                           | NotifyFilters.DirectoryName;
                        watcher.Path = Path.GetDirectoryName(s_LoadFilePath);
                        watcher.Filter = Path.GetFileName(s_LoadFilePath);
    
                        try
                        {
                            watcher.Created += OnConfigFileCreate;
                            watcher.EnableRaisingEvents = true;
    
                            // Now just sit here and wait until hell freezes over
                            // or until the user tells us that it has
                            string line = string.Empty;
                            while (!string.Equals(line, ExitString, StringComparison.OrdinalIgnoreCase))
                            {
                                line = Console.ReadLine();
                            }
                        }
                        finally
                        {
                            watcher.Created -= OnConfigFileCreate;
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
    
            private static void RunApplication(string configFilePath)
            {
                var appPath = string.Empty;
                var arguments = string.Empty;
                using (var reader = new StreamReader(configFilePath, Encoding.UTF8))
                {
                    appPath = reader.ReadLine();
                    arguments = reader.ReadLine();
                }
    
                // Run the application
                StartProcess(appPath, arguments);
            }
    
            private static void StartProcess(string path, string arguments)
            {
                var startInfo = new ProcessStartInfo();
                {
                    startInfo.FileName = path;
                    startInfo.Arguments = arguments;
                    startInfo.ErrorDialog = false;
                    startInfo.UseShellExecute = true;
                    startInfo.RedirectStandardOutput = false;
                    startInfo.RedirectStandardError = false;
                }
    
                Console.WriteLine(
                    string.Format(
                        CultureInfo.InvariantCulture, 
                        "{0} Starting process {1}", 
                        DateTime.Now, 
                        path));
    
                using (var exec = new Process())
                {
                    exec.StartInfo = startInfo;
                    exec.Start();
                }
            }
    
            private static void OnConfigFileCreate(
                object sender, 
                FileSystemEventArgs e)
            {
                Console.WriteLine(
                   string.Format(
                      CultureInfo.InvariantCulture,
                      "{0} File change event ({1}) for: {2}",
                      DateTime.Now,
                      e.ChangeType,
                      e.FullPath));
    
                // See that the file is there. If so then start the app
                if (File.Exists(e.FullPath) &&
                   string.Equals(s_LoadFilePath, e.FullPath, StringComparison.OrdinalIgnoreCase))
                {
                    // Wait for a bit so that the file is no 
                    // longer locked by other processes
                    Thread.Sleep(500);
    
                    // Now run the application
                    RunApplication(e.FullPath);
                }
            }
        }
    }
    

此应用程序期望文件有 2 行,第一行包含您要启动的应用程序,第二行包含参数,因此在您的情况下,如下所示:

C:\Program Files\Automated QA\TestComplete 7\Bin\TestComplete.exe
"D:\Test Complete7 Projects\ProjectInput_AllSamples\ProjecInputs.pjs" /r /p:Samples /rt:Main "iexplore" /e

您应该能够在构建步骤中从 Jenkins 生成此文件。

最后,您可能需要观看 TestComplete 过程的退出,以便您可以在最后获取结果,但我会将其作为练习留给读者。

关于jenkins - 当从 jenkins 调用时,无法在 testcomplete 中运行自动化项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15134460/

相关文章:

Jenkins email-ext 预发送 groovy 脚本生成附件

azure - 使用Azure Webjobs和计划部署Web项目时如何启用非交互式身份验证?

svn - 当 jenkins 轮询 SCM 时忽略 pom.xml 提交

java - PowerMock PrepareForTest 注释导致 AmazonSQSClient 构造函数出现问题

continuous-integration - 如何将 Play 与自定义模块和持续集成一起使用

jenkins-plugins - 如何通过jenkins插件或命令行在stash(Bitbucket服务器)上创建Pull Request

maven - sonar maven 插件构建错误,SonarQube 版本 : null

django - 如何使用 CI/CD 和 Google CloudSQL 迁移 django 中的数据库?

azure - Azure DevOps 管道中的 "Job is pending"消息

Jenkins 未满足的资格