phpunit异常退出SIGALRM

Posted by

最近遇到一个奇怪的单元测试经历,刚开始发现单个测试文件运行正常,后面整个项目的单元测试启动起来后,总是异常退出,控制台输出“Process finished with exit code 142 (interrupted by signal 14: SIGALRM)”,初步看起来是异常退出。但是我单个测试用例执行是正常的,令人不解。

单元测试结构如下

tests
    /service
        OneTest.php
        TwoTest.php
        ThreeTest.php

单个测试文件运行无异常,但是一起运行之后就发现出错。后面采用排除法,我一一把指定的文件加载进来进行测试,发现就是TwoTest.php加载进来的时候,一起测试失败。

于是,我单独对Two这个文件又单独运行,正常。真是奇了怪了~!我对比其他文件,发现这个里面唯一不同的就是该测试包含了http请求,于是我把请求的过程去掉,果然又没有问题。这个里面有一个细节就是,该文件的测试方法都使用了dataProvider,各自3个数据项,这样加起来就一共是6个测试,6个请求。这样子我就开始怀疑了,难道这调用还加了次数限制?于是我尝试把请求次数缩减到4次,3次。这个时候发觉正常了,3次的时候就正常了。我顺着代码找了进去,并没有找到有关的限制。

上述的调用因为涉及到了第三方组件,于是我单独把该组件拿了出来,做一个空的项目,加载进来之后再次运行。同样的场景,我将请求加到了6次,没有任何问题,于是可以排除是组件的问题。

回到原项目中,开始关注起提示来:SIGALRM,我翻了一下linux的信号,于是找到了下一个线索:pcntl_alarm,为进程设置一个alarm闹钟信号。我在项目中检索了一下该方法,发现就只有两处使用,第一个就是phpunit中的,用来配置测试用例运行时间的;第二个就是项目本身框架里的信号配置。

我顺着phpunit的文档和底层代码,将涉及的单元测试方法配置了注解“large”,发现并没有效果,看底层代码也是一样,默认的配置的为0,不会有影响,这个被排除。

找来第二个疑点,框架自身带有的Timer类,用来配置信号,但是我在单元测试的启动文件中并没有执行框架里的方法。于是利用IDEA自身的反引用检索,搜了一下,找到了,原来隐藏在配置文件的加载过程中,会涉及一个数据库的配置心跳。我阅读了一下Timer的源码,于是在启动文件中加上了针对载入的信号处理collection进行了unset。再次测试,终于顺利执行完,通过了。

问题解决了,再次回到问题本身,此次问题的起因就是因为配置了该闹钟信号,在单元测试启动运行的时候,一旦运行时间超过该时间,控制台就会接收该信号,但是由于没有后期方法进行处理,所以造成单元测试直接退出了。

中途我还做了一个小实验,把原先的http请求全部都注释掉,直接使用sleep来代替,发现只要超过一秒钟的时候,就会出现一样的错误。于是在后面找到问题点后,我看到源码,那里正写着\pcntl_alarm(1)!

问题解决最后,还是给到一个深刻的反思:出现问题的时候,不应该忽略提示,它总是有意义的!

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注