Ich teste einen URL-Abruf als Einheit und benötige eine Test-URL, die immer zu einer Zeitüberschreitung von urllib2.urlopen() (Python) führt. Ich habe versucht, eine PHP-Seite mit nur Schlaf (10000) darin zu erstellen, aber das verursacht 500 interne Serverfehler.

Wie würde ich eine Ressource erstellen, die bei jeder Anforderung ein Verbindungszeitlimit im Client verursacht?

3
user1552512 6 Okt. 2012 im 00:22

5 Antworten

Beste Antwort

Obwohl es hier einige gute Antworten gab, stellte ich fest, dass ein einfacher PHP-Sleep () -Aufruf mit einer Überschreibung von Apaches Timeout alles war, was ich brauchte.

Ich weiß, dass Unit-Tests isoliert sein sollten, aber der Server, auf dem dieser Endpunkt gehostet wird, funktioniert nirgendwo.

0
user1552512 17 Okt. 2012 im 19:26

Verbindungszeitüberschreitung? Verwenden Sie beispielsweise netcat. Lauschen Sie einem Port (nc -l) und versuchen Sie dann, Daten von diesem Port herunterzuladen. http://localhost:port/. Es wird eine Verbindung geöffnet, die niemals antwortet.

1
nothrow 5 Okt. 2012 im 20:31

Haben Sie versucht, httpbin /delay zu verwenden?

Httpbin ist ein HTTP-Anforderungs- und Antwortdienst , der in Python geschrieben wurde (ich denke, Kenneth Reitz hat ihn entwickelt, um zu testen. > requests Modul beim Schreiben), Quelle ist auf GitHub. Ich bin mir nicht sicher, ob /delay das Akzeptieren der Anforderungsverbindung oder das Senden der Antwort verzögert. Wenn es jedoch nicht genau Ihren Anforderungen entspricht, sollte es sehr einfach zu ändern oder zu erweitern sein.

4
Lukas Graf 5 Okt. 2012 im 20:50

In PHP können Sie einen Header mit dem Statuscode 408 senden

header("HTTP/1.0 408 Request Timeout");
0
Brian Glaz 5 Okt. 2012 im 20:28

Bearbeiten: Ich habe das [php] -Tag gesehen und nur angenommen, dass dies PHP-Code ist - In Python können jedoch dieselben Prinzipien gelten, wenn dies die Sprache ist, mit der Sie arbeiten.

Für einen erfolgreichen Komponententest müssen Sie Codeeinheiten vollständig isoliert von allen äußeren Einflüssen testen. Dies bedeutet, dass Sie es falsch machen, wenn Ihr Test davon abhängt, dass das Dateisystem (oder in diesem Fall ein externer Webserver) ordnungsgemäß funktioniert. Wenn Ihre Tests von einem externen Webserver abhängen, erhöhen Sie die Komplexität des Testcodes erheblich und führen die Möglichkeit von Fehlalarmen und anderen fehlerhaften Testergebnissen ein.

Es hört sich so an, als ob die aktuelle Testimplementierung einen vollständigen Mock-Webserver erfordert, um bestimmte, testbare Antworten zu liefern. Dies sollte nicht der Fall sein . Solche weitreichenden Testabhängigkeiten führen nur zu den oben beschriebenen Problemen.

Ein besserer Weg

Aber wie testen Sie die native PHP-Funktionalität und ihre Interaktionen mit entfernten Daten (wie HTTP oder FTP)? Die Antwort besteht darin, Ihrem Code Test "Nähte" hinzuzufügen. Betrachten Sie das folgende einfache Beispiel:

<?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); 
    }
}

Und Ihr relevanter PHPUnit-Test würde ungefähr so aussehen:

<?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);
    }
}

Natürlich ist dieses Beispiel erfunden und äußerst einfach, aber das Konzept lässt sich so weit skalieren, wie Sie es benötigen. Durch das Erstellen von Testnähten wie der obigen UrlRetriever::doRetrieve -Methode können wir die Ergebnisse mithilfe von Standardtest-Frameworks leicht verspotten.

Mit dieser Methode können wir das ansonsten komplizierte Ergebnis nativer PHP-Funktionen testen, die Remote-Ressourcen manipulieren, ohne jemals einen externen Webserver berühren zu müssen oder die Möglichkeit von Fehlern außerhalb des zu testenden Systems einzuführen.

Wenn im speziellen Fall des OP ein Timeout-Ergebnis gewünscht wird, verspotten Sie einfach die entsprechende Testnahtmethode, um das zu tun, was die native PHP-Funktion im Falle eines Timeouts tun würde.

5
rdlowrey 5 Okt. 2012 im 22:10