Robot Framework 中的“坑” - Start Process

Library 'Process' 中有个 keyword 'Start Process'。

Starts a new process on background)

注:Library 'OperatingSystem' 中也有个 keyword 'Start Process'。但是已被废弃,建议用 Process.Start Process。

 

=== 这部分是我发现这个“坑”的经过。不感兴趣的,可直接跳到文末 ===

最近遇到个问题。

> 现象

注:被测系统 (SUT) 是一个 WinForm 程序,用 C# .Net 编写

  • 在执行某个 Case 时,手动执行一切正常
  • 但是用 Robot Framework 执行时,总是执行到某个固定步骤时 SUT 卡死
  • (接上一步)此时,如果停掉 Robot Framework,SUT 又能继续执行,正常结束
  • 同一个 Case 在测试以前的版本没有这个问题。

> 经过

刚接到这个任务时,我首先怀疑是 Case 的脚本有所不妥,导致被测系统被影响。

(毕竟手动执行没问题)

于是:

  1. 研究了被测系统卡死时 Robot Framework 正在执行的那个 keyword。无果。该 keyword(我自己实现的):在固定时间内不断检测被测系统是否有弹出消息框,直到消息框弹出或超时。我也考虑过是不是 UIAutomation 底层实现导致:Robot Framework 不断检测 SUT 的 UI;SUT 又要不断更新 UI(刷新各种界面特效)。想了想感觉可能性不大,接着考虑其它原因。
  2. Review 整条 Case 执行线。无果。
  3. 然后用排除法(半自动化):手动启动 SUT自动执行后续步骤。SUT 顺利执行完毕。

于是猜测是脚本中,启动 SUT 的方式导致的。

把启动方式从
Process.Start Process    ${SUT.exe}

Start Process    ${SUT.exe}
改为

Evaluate    subprocess.Popen(['${SUT.exe}'])    subprocess

Evaluate    subprocess.Popen(['${SUT.exe}'])    subprocess

 

经测试,SUT 顺利执行完毕。
为了不 delay 测试业务太多时间,先用上这个新方案,具体问题原因自己再慢慢研究。

拿到 SUT 源码,开始调试

发现如果用 Start Process 启动 SUT,SUT 在某处调用 Console.WriteLine 时会卡死。

这个语句在一个循环中,而且每次都是执行循环固定次数后卡死。

此时隐约感觉是输出被重定向后遇到最大输出数据的限制了。

然后就是后续的一些对比实验验证了该想法。

=== 发现过程结束 ===

 

Process.Start Process    ${SUT.exe}

vs

Evaluate    subprocess.Popen(['${SUT.exe}'])    subprocess

 

其实这两者底层都调用了 subprocess.Popen,但是传给 Popen 的参数有所不同。

 

  1. Start Process 在内部会对参数赋予一些特定的默认值;
  2. 其中,子进程的输出被重定向为 subprocess.PIPE;
  3. 输出被重定向到一个流,而且这个没有任何读者(除非用户主动发起相关操作);
  4. 如果子进程不断往这个输出流写数据,会导致流中数据越来越多(没有被读出去),并达到限制的最大值;
  5. 然后子进程就被卡死在下一次写操作上 (流已满,无法写入)。

MSDN 上的一些示例也有对这类死锁的一些说明:Process.StandardOutput Property

展开阅读全文

没有更多推荐了,返回首页