2012-08-03 27 views
7

Ich bekomme eine JSON-Struktur von einer API und muss überprüfen, ob die erfolgreiche Antwort zwei spezifische Attribute mit bestimmten Werten hat.So testen Sie mehrere Eigenschaften eines Objekts

Schlüsselprobleme:

  1. ich nicht das ganze Objekt vergleichen, da es einige Eigenschaften, die mit jeder Anforderung variieren können
  2. ich nicht zwei Tests schreiben kann (für jedes Attribut), weil es sein kann, wird nur dann als erfolgreiche Antwort betrachtet, wenn beide Attribute den richtigen Werten entsprechen.

Beispiel erfolgreiche Antwort:

{ 
    'success': true, 
    'user_ip': '212.20.30.40', 
    'id': '7629428643' 
} 

Schmutzige Lösung wäre

<?php 
public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    $this->assertTrue(
     $response->success === TRUE && 
     $response->id === '7629428643' 
    ); 
} 

Aber ich denke, es muss bessere und sauberere Lösung sein, oder?

+2

Das sieht ziemlich sauber zu mir. – Matt

+0

Diese Lösung kann Ihnen nur sagen, dass der Test fehlschlägt, aber kann Ihnen nicht sagen, was genau schief geht, das ist meistens, warum ich das als "schmutzig" betrachte. –

Antwort

0

Wenn assertTrue() den Booleschen Wert einer erfolgreichen Antwort speichert, ist dies der Weg, wie ich damit umgehen würde. Denken Sie daran, dass dies eine Frage von Geschmack ist.

private $lastResponse; 
// $id given elsewhere 
public function testAddAccount($id) { 
    $this->lastResponse = $this->addAccount($id); 
} 

private function addAccount($id) { 
    return $this->api->addAccount($id); 
} 

private function isLastResponseValid($response){ 
    return $this->lastResponse->success === TRUE 
    && $this->lastResponse->id === '7629428643'; 
} 
0

Sie können mehrere Assertions in einer einzigen Testmethode für solche Fälle verwenden. Verwenden Sie auch die spezifischeren Assertionen, wie z. B. assertEquals, wann immer dies möglich ist, da diese bessere Fehlermeldungen liefern.

public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    self::assertTrue($response->success); 
    self::assertEquals('7629428643', $response->id); 
} 
0

Wie in einigen Antwort erwähnt, sollten Sie assertEquals() Methode verwenden. Der zweite Teil besteht darin, dass Sie einige Behauptungen verwenden können. Wenn das phpunit bei der ersten Assertion einen Fehler erkennt, schlägt der gesamte Test fehl.

Warum nicht assertTrue() verwenden? Weil es nicht klar ist, ob Sie beispielsweise if ($object) ... an einer Stelle und assertTrue($object); in einer anderen Stelle verwenden.

Stellen Sie außerdem sicher, dass Ihre Routine ordnungsgemäß ausgeführt wird. Wenn Sie also die Ausnahme erhalten, während Sie versuchen, die Antwort zu erhalten, wird der Test fehlschlagen. Während Ausnahmen sollten auch als Testfälle überprüft werden. Das heißt, Sie sollten versuchen, eine falsche Anfrage zu posten, und eine Ausnahme wird ausgelöst. Das ist, wie gut Test aussieht - es sollte alle möglichen Situationen überprüfen, hehe =)

Also, das ist der Code, den Sie bekommen sollte:

public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    $this->assertEquals($response->success, true); 
    $this->assertEquals($response->id, '7629428643'); 

    $this->setExpectedException('MyException'); 

    $response = $this->api->addAccount('wrong_account'); 
} 
2

Sie möchten für jede Eigenschaft assertEquals() verwenden Sie überprüfen möchten . Während Sie normalerweise nur eine Sache in jedem Testfall testen möchten, sind manchmal mehrere Behauptungen erforderlich, um diese "eine Sache" zu testen. Aus diesem Grund sind mehrere Behauptungen in Ordnung.

Sie können auch behaupten, dass die Eigenschaften auf dem $response Objekt vorhanden sind, um Hinweise zu vermeiden.die folgenden für ein Beispiel siehe:

public function testAddAccount() { 
    // Attempt to create an account. 
    $response = $this->api->addAccount('7629428643'); 

    // Verify that the expected properties are present in the response. 
    $this->assertObjectHasAttribute('success', $response); 
    $this->assertObjectHasAttribute('id', $response); 

    // Verify the values of the properties. 
    $this->assertEquals(true, $response->success); 
    $this->assertEquals('7629428643', $response->id); 
} 
+0

Dennoch hat es einen Fehler in der Art und Weise, dass es im Falle des Scheiterns zeigt, dass Sie nur die erste problematische Behauptung versagen, sobald Sie es beheben, zeigt es Ihnen eine andere. –

+0

Das ist richtig, aber es ist am besten, sich immer nur auf einen Fehler zu konzentrieren. Es ist nicht ungewöhnlich, dass das Beheben des ersten Fehlers auch verbleibende Fehler innerhalb eines Testfalls auflösen wird. – JamesArmes

0

Die sauberste Art, wie ich mir vorstellen kann (obwohl dies ist Geschmackssache) wäre, die beiden Booleschen Ausdrücken zu addieren und das Ergebnis behaupten zwei:

$r1=$response->success === TRUE; 
$r2=$response->id === '7629428643'; 
$this->assertEquals(2, $r1+$r2, "Expecting both values to match; got ($r1) and ($r2)"); 

Natürlich können Sie dieses Setup auf eine beliebige Anzahl von Tests mit Arrays und array_sum()==count() und mehr liebenswerte Nachrichten erweitern.

1

Berechnen Sie den Unterschied zwischen der Antwort und der richtigen Antwort, wobei Sie übermäßige Werte ignorieren. Wenn es keinen Unterschied gibt, ist alles in Ordnung; Wenn ja, erhalten Sie die vollständigen Informationen.

//some examples 
$responseValues = array('success' => true, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //success 
$errorResponseValues = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //failure 
$errorResponseValues2 = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '123'); //failure 

$expectedValues = array('success' => true, 'id' => '7629428643'); //what is success 

function whatIsWrong($reality, $expectation) 
{ 
    return array_uintersect_assoc($reality, $expectation, function($a, $b){return (int)($a == $b);}); //This is slightly dirty, I think the final implementation is up to you 
} 

var_dump(whatIsWrong($responseValues, $expectedValues)); //array() 
var_dump(whatIsWrong($errorResponseValues, $expectedValues)); //array('success' => false) 
var_dump(whatIsWrong($errorResponseValues2, $expectedValues)); //array('success' => false, id => 123) 

Dann können Sie assertEqual (whatIsWrong (...), array()) verwenden, was der Unterschied bei einem Fehler ausgegeben werden soll, oder es in so ziemlich jeder bevorzugten Art und Weise handhaben.

Verwandte Themen