我应该如何创建一个总是超时的测试资源

use*_*512 3 php python apache url timeout

我正在测试一个URL提取器,我需要一个测试URL,它总是会导致urllib2.urlopen()(Python)超时.我已经尝试制作一个只有睡眠(10000)的php页面,但这会导致500内部服务器错误.

每当请求时,我如何创建一个导致客户端连接超时的资源?

Luk*_*raf 5

你试过httpbin/delay

httpbin 是用 Python 编写的HTTP 请求和响应服务(我认为 Kenneth Reitz 开发它是为了requests在编写模块时测试模块),源在GitHub 上。我实际上不确定是否/delay会延迟接受请求连接或发送响应。但是如果它不能完全满足您的需求,那么修改或扩展它应该很容易。


rdl*_*rey 5

编辑:我看到[php]标签,并假设这是PHP代码 - 但是,如果这是您正在使用的语言,相同的原则可以应用于Python.

成功的单元测试要求您完全隔离所有外部影响来测试代码单元.这意味着如果您的测试依赖于文件系统(或者在某些情况下是某些外部Web服务器)之类的东西来正常运行,那么您做错了.当您的测试依赖于外部Web服务器时,您会增加测试代码的复杂性,并引入误报和其他错误测试结果的可能性.

听起来当前的测试实现需要一个成熟的模拟Web服务器来提供特定的,可测试的响应.情况并非如此.这种影响深远的测试依赖性只会导致上述问题.

更好的方式

但是,您如何测试本机PHP功能及其与远程数据(如HTTP或FTP)的交互?答案是在代码中添加测试"接缝".考虑以下简单示例:

<?php

class UrlRetriever {

    public function retrieve($uri) {
        $response = $this->doRetrieve($uri);
        if (false !== $response) {
            return $response;
        } else {
            throw new RuntimeException(
                'Retrieval failed for ' . $uri
            );
        }
    }

    /**
     * A test seam to allow mocking of `file_get_contents` results
     */
    protected function doRetrieve($uri) {
        // suppress the warning from a failure since we're testing against the
        // return value (FALSE on failure)
        return @file_get_contents($uri); 
    }
}
Run Code Online (Sandbox Code Playgroud)

您的相关PHPUnit测试看起来像这样:

<?php

class UrlRetrieverTest extends PHPUnit_Framework_TestCase {

    /**
     * @covers UrlRetriever::retrieve
     * @expectedException RuntimeException
     */
    public function testRetrieveThrowsExceptionOnFailure() {
        $retriever = $this->getMock('UrlRetriever', array('doRetrieve'));
        $retriever->expects($this->once())
                  ->method('doRetrieve')
                  ->will($this->returnValue(false));

        $retriever->retrieve('http://someurl');
    }

    /**
     * @covers UrlRetriever::retrieve
     */
    public function testSomeSpecificOutputIsHandledCorrectly() {
        $expectedValue = 'Some value I want to manipulate';

        $retriever = $this->getMock('UrlRetriever', array('doRetrieve'));
        $retriever->expects($this->once())
                  ->method('doRetrieve')
                  ->will($this->returnValue($expectedValue));

        $response = $retriever->retrieve('http://someurl');
        $this->assertEquals($response, $expectedValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,这个例子是人为的,而且非常简单,但这个概念可以根据你的需要进行扩展.通过像上述UrlRetriever::doRetrieve方法一样创建测试接缝,我们可以使用标准测试框架轻松模拟结果.

这种方法允许我们测试操作远程资源的本机PHP函数的复杂结果,而不必触及外部Web服务器或在被测系统之外引入错误的可能性.

在OP的特定情况下,如果需要超时结果,只需模拟相关的测试接缝方法,以执行本机PHP函数在超时时执行的操作.