Skip to content

Commit

Permalink
Merge pull request #54 from tyx/feature/deal-with-failure
Browse files Browse the repository at this point in the history
🆕 Introduce RestApiBrowser::sendRequestUntil
  • Loading branch information
shouze authored Oct 27, 2016
2 parents 0c2a739 + 4d4a402 commit 853a48f
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 4 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"psr/http-message": "^1.0",
"php-http/discovery": "^1.0",
"php-http/client-common": "^1.2",
"php-http/message": "^1.3"
"php-http/message": "^1.3",
"tolerance/tolerance": "^0.3.2"
},
"require-dev": {
"silex/silex": "~1.0",
Expand Down
6 changes: 3 additions & 3 deletions features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ public function iRunBehat($arguments)
public function itShouldTerminateWithStatusAndContent($exitStatus, PyStringNode $string)
{
if ('fail' === $exitStatus) {
$this->asserter->variable($this->getExitCode())->isEqualTo(1);
} elseif ('success' === $exitStatus) {
$this->asserter->variable($this->getExitCode())->isEqualTo(0);
$this->asserter->integer($this->getExitCode())->isEqualTo(1);
} elseif ('pass' === $exitStatus) {
$this->asserter->integer($this->getExitCode())->isEqualTo(0);
} else {
throw new \LogicException('Accepts only "fail" or "pass"');
}
Expand Down
126 changes: 126 additions & 0 deletions features/send_request_until.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
Feature: Send request until
In order to test async system
As a developer
I should be able to try to send HTTP request until it validates my requirement

Background:
Given a file named "behat.yml" with:
"""
default:
extensions:
Rezzza\RestApiBehatExtension\Extension:
rest:
base_url: http://localhost:8888
suites:
default:
contexts:
- FeatureContext
- Rezzza\RestApiBehatExtension\RestApiContext
"""

Scenario: Send request until it works
Given a file named "features/send_request_until.feature" with:
"""
Feature: Send request until
In order to deal with async system
As a feature runner
I need to continue to send request until it works
Scenario: Send request that could fail
When I call my microservice
And I call my microservice
And I call my microservice
Then print response
"""
And a file named "features/bootstrap/FeatureContext.php" with:
"""
<?php
use Behat\Behat\Context\Context;
use Rezzza\RestApiBehatExtension\Rest\RestApiBrowser;
use mageekguy\atoum\asserter;
class FeatureContext implements Context
{
private $restApiBrowser;
private $asserter;
public function __construct(RestApiBrowser $restApiBrowser)
{
$this->restApiBrowser = $restApiBrowser;
$this->asserter = new asserter\generator;
}
/**
* @When I call my microservice
*/
public function callMyMicroservice()
{
$restApiBrowser = $this->restApiBrowser;
$asserter = $this->asserter;
$this->restApiBrowser->sendRequestUntil(
'GET', 'error_random', null, function () use ($restApiBrowser, $asserter) {
$asserter->integer($restApiBrowser->getResponse()->getStatusCode())->isEqualTo(200);
}
);
}
}
"""
When I run behat "features/send_request_until.feature"
Then it should pass with:
"""
200 OK
"""

Scenario: Send request that will fail always
Given a file named "features/send_request_until.feature" with:
"""
Feature: Send request until
In order to deal with async system
As a feature runner
I need to continue to send request until it works
Scenario: Send request that fail
When I call my microservice
Then print response
"""
And a file named "features/bootstrap/FeatureContext.php" with:
"""
<?php
use Behat\Behat\Context\Context;
use Rezzza\RestApiBehatExtension\Rest\RestApiBrowser;
use mageekguy\atoum\asserter;
class FeatureContext implements Context
{
private $restApiBrowser;
private $asserter;
public function __construct(RestApiBrowser $restApiBrowser)
{
$this->restApiBrowser = $restApiBrowser;
$this->asserter = new asserter\generator;
}
/**
* @When I call my microservice
*/
public function callMyMicroservice()
{
$restApiBrowser = $this->restApiBrowser;
$asserter = $this->asserter;
$this->restApiBrowser->sendRequestUntil(
'GET', 'always_error', null, function () use ($restApiBrowser, $asserter) {
$asserter->integer($restApiBrowser->getResponse()->getStatusCode())->isEqualTo(200);
},
5
);
}
}
"""
When I run behat "features/send_request_until.feature"
Then it should fail with:
"""
integer(502) is not equal to integer(200)
"""
19 changes: 19 additions & 0 deletions src/Rest/RestApiBrowser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
use Http\Discovery\MessageFactoryDiscovery;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Tolerance\Operation\Callback;
use Tolerance\Operation\Runner\RetryOperationRunner;
use Tolerance\Operation\Runner\CallbackOperationRunner;
use Tolerance\Waiter\SleepWaiter;
use Rezzza\RestApiBehatExtension\Tolerance\ExecutionTimeLimited;

class RestApiBrowser
{
Expand Down Expand Up @@ -102,6 +107,20 @@ public function sendRequest($method, $uri, $body = null)
}
}

public function sendRequestUntil($method, $uri, $body, callable $assertion, $maxExecutionTime = 10)
{
$runner = new RetryOperationRunner(
new CallbackOperationRunner(),
new ExecutionTimeLimited(new SleepWaiter(), $maxExecutionTime)
);
$restApiBrowser = $this;
$runner->run(new Callback(function () use ($restApiBrowser, $method, $uri, $body, $assertion) {
$restApiBrowser->sendRequest($method, $uri, $body);

return $assertion();
}));
}

/**
* @param string $name
* @param string $value
Expand Down
46 changes: 46 additions & 0 deletions src/Tolerance/ExecutionTimeLimited.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Rezzza\RestApiBehatExtension\Tolerance;

use Tolerance\Waiter\Waiter;
use Tolerance\Waiter\StatefulWaiter;

class ExecutionTimeLimited implements Waiter, StatefulWaiter
{
/**
* @var Waiter
*/
private $waiter;

private $maxExecutionTime;

private $timeEllapsed;

public function __construct(Waiter $waiter, $maxExecutionTime)
{
$this->waiter = $waiter;
$this->maxExecutionTime = $maxExecutionTime;
$this->timeEllapsed = 0;
}

/**
* {@inheritdoc}
*/
public function wait($seconds = 1)
{
$this->timeEllapsed += $seconds;
if ($this->maxExecutionTime < $this->timeEllapsed) {
throw MaxExecutionTimeReached::withValue($this->maxExecutionTime);
}
$this->waiter->wait($seconds);
}

/**
* {@inheritdoc}
*/
public function resetState()
{
// wait for 0.4.0 to have https://github.com/Tolerance/Tolerance/pull/67
// $this->timeEllapsed = 0;
}
}
13 changes: 13 additions & 0 deletions src/Tolerance/MaxExecutionTimeReached.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rezzza\RestApiBehatExtension\Tolerance;

use Tolerance\Waiter\WaiterException;

class MaxExecutionTimeReached extends WaiterException
{
public static function withValue($maxExecutionTime)
{
return new static(sprintf('Max execution "%s seconds" time is reached', $maxExecutionTime));
}
}
14 changes: 14 additions & 0 deletions www/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,19 @@ function(Request $req) {
return $response;
}
);
$app->match(
'error_random',
function (Request $request) {
$statusCode = time() % 3 <= 0 ? 200 : 502 ;

return new JsonResponse([], $statusCode);
}
);
$app->match(
'always_error',
function (Request $request) {
return new JsonResponse([], 502);
}
);

$app->run();

0 comments on commit 853a48f

Please sign in to comment.