【问题标题】:Is it possible use keyboard actions without using the "PyAutoGUI" library on jenkins?是否可以在不使用 jenkins 上的“PyAutoGUI”库的情况下使用键盘操作?
【发布时间】:2018-07-17 04:58:36
【问题描述】:

我正在使用 Robotframework 为应用程序创建测试脚本。此应用程序需要许多不可避免的键盘单击/操作组合。现在我正在使用 PyAutoGui 库来模拟这些动作并且它们工作正常,但是当我通过 Jenkins 上的无头浏览器运行它们时,这些动作没有注册。

我得到的错误是“PyAutoGUI 故障安全由鼠标移动到左上角触发。要禁用此故障安全,请将 pyautogui.FAILSAFE 设置为 False。” 但是,即使将 Failsafe 值更改为 false,仍然无法捕获键盘操作。

奇怪的是,如果有人在测试运行时以物理方式登录到 Jenkins 框,则库工作得非常好,但是当无头运行时,库会中断。

对于这种情况,我可以使用另一个库或可能的解决方法吗?

提前致谢!

【问题讨论】:

  • 我认为 PyAutoGUI 依赖于一个显示屏,它可以是物理的或虚拟的。如果您在机器桌面上登录,然后在无头模型的 cmd 窗口中运行脚本,PyAutoGUI 应该可以正常工作。但是如果你通过Putty之类的工具登录机器,实际上你登录的是机器的终端而不是桌面,在终端默认情况下是不显示屏幕的。非Windows机器经常出现这样的问题,那么你的Jenkins盒子是Window还是Linux?
  • 我们使用的Jenkins盒子是windows,可惜我们无权访问。唯一有权访问它的人是管理员,但每次我们需要触发测试时,他都无法登录虚拟机并为我们运行作业。
  • 还有其他库可以用来传递键盘动作/事件吗?我找到了适用于 Windows 的“sendKeys”模块,但我还没有机会在 VM 中对其进行测试。
  • Selenium sendKeys() 可以按组合键,如 Ctrl + A 等,以及 Action 类执行鼠标移动/向下/向上。两者都可以满足您的所有要求吗?
  • 但是这可以通过虚拟机在 Jenkins 上运行吗?我目前遇到的问题是 pyautogui 无法在虚拟机上运行。本地 pyautogui 可以很好地模拟不同的键盘操作,但由于某些原因在 Jenkins 上它不起作用。

标签: python selenium jenkins automation robotframework


【解决方案1】:

这种行为的原因是当没有用户登录(物理或通过 RDP)时,没有活动的桌面(想想所有的 GUI 元素、配置文件等)我们在我们的环境中遇到了这样的问题。这是一个可行的解决方案:

  1. 创建一个将在 Windows VM 上建立 RDP 会话的作业,以便有一个活动桌面。该作业无法结束 RDP 会话。它需要在后台运行(通常没问题,就像其他人使用同一用户登录一样,会话将切换到新用户但桌面将处于活动状态。)
  2. 确保在 Win VM 上运行测试作业时,已经打开了一个 RDP。安排作业 1 在 Win VM 上进行测试之前运行。

从作业 1 的技术细节来看,我们的 WinVM 节点以 WIN 前缀命名,因此要获取所有 Windows 节点,我们通过 Jenkins API 查询 Jenkins。
一旦我们有了 WinVMs 列表(IP 或主机名),我们在 Linux 节点上运行以下命令,循环所有发现的 WinVMs 节点。

一个节点的基本命令:

   BUILD_ID=dontKillMe vncserver -kill :100 || true
   BUILD_ID=dontKillMe rm -rf /tmp/.X11-unix/X100 || true 
   BUILD_ID=dontKillMe vncserver :100
   BUILD_ID=dontKillMe DISPLAY=localhost:100
   BUILD_ID=dontKillMe export DISPLAY
   yum install -y freerdp
   ## loop through WinVMs below:    
   nohup xfreerdp -g <resolution> -u <user> -p <pas> <IP/hostname>
   ## end of loop

nohup 的神奇之处在于,它会在作业完成后在后台运行 RDP 会话。

这是安装了 vncserverxfreerdp 的 Centos。

#编辑

您可以要求管理员创建一个 WinVM 来运行测试,将 Jenkins 与开发/测试环境分开。通过这种方式,您可以从任何地方或 Jenkins 本身在节点上打开 RDP 会话。为了稳定性和性能,最好不要在 master 上运行任何东西。

【讨论】:

    【解决方案2】:

    我在工作中一直在自动化许多 Web 应用程序。

    我也是从 PyAutoGUI 开始的,在从我的笔记本电脑到运行脚本的生产服务器时遇到了类似的问题。

    我找到的解决方案是 Selenium Webdriver。如果您正在测试的有一个 IP 地址,这可能是解决方案。在我看来,它实际上比 PyAutoGUI 更容易。

    【讨论】:

    • 我可以将 Selenium Webdriver 与 Robotframework 一起使用吗?因为我们的整个自动化项目都是用 Robotframework 构建的,是否可以将 webdriver 实例从机器人传递给 selenium,以便我们可以继续在 selenium 中进行测试?或者使用 selenium web driver 意味着整个项目只使用 selenium?
    • 我没有测试过,所以我不确定两者会如何交互。我会留下评论而不是答案,但我没有足够的代表来做到这一点。 Selenium 可能不可行,我只是想我会把这个想法扔出去。
    【解决方案3】:

    您可以通过安装 VNC 服务器并在其中运行 jenkins slave 来解决此问题。然后浏览器将以 gui 启动并进行测试。

    【讨论】:

      【解决方案4】:

      我能够为我的问题找到解决方案/解决方法。我在谷歌群组上看到了这篇关于机器人框架自动化中的多个组合键的帖子,它能够帮助我找到一个可行的解决方案。我们可以使用 sendKeys 构建自定义关键字来组合多个键盘操作,而不是尝试使用 pyautogui 库。这种方法对我来说非常有效,唯一的缺点是现在我必须通过一个选择器来关注每次我想使用我的自定义关键字时,但对于我的应用程序来说这不是一个大问题。

      我从Discussion 中提取了代码并做了一些细微的修改:

      def customPressKey(self, locator, keys):
          keys =  keys.split(' + ')
          i = 0
          named_keys = []
          named_key_sequence = []
          named_key_seq_as_string = ''
          unnamed = '' 
          for key in keys:
          try:
              named_key = getattr(Keys, keys[i])
              print "%s. named key is %s." % (i + 1, key)
              named_keys.append(keys[i])
              i = i + 1
              except:
                  print "The rest '%s' is unnamed." % key
                  unnamed = str(key).lower()
                  i = i + 1
          print "NAMED KEY(s):", named_keys
          for key in named_keys:
              named_key_sequence.append('Keys.%s' % key)
              named_key_seq_as_string = ','.join(named_key_sequence)
          print "NAMED KEY SEQUENCE:", named_key_sequence
          print "NAMED KEY SEQUENCE as STRING:", named_key_seq_as_string
          print "element.send_keys() call should look like this:"
          print "element.send_keys(%s, '%s')" % (named_key_seq_as_string, unnamed)
          element = self.find_element(locator)
          if unnamed:
              exec("element.send_keys(%s, '%s')" % (named_key_seq_as_string, unnamed))
          else:
              exec("element.send_keys(%s)" % (named_key_seq_as_string))
      

      【讨论】:

        猜你喜欢
        • 2021-03-14
        • 2021-09-04
        • 2012-07-22
        • 2015-08-01
        • 2015-06-24
        • 2020-05-16
        • 1970-01-01
        • 2023-01-11
        • 2017-08-04
        相关资源
        最近更新 更多