I am a quite newbee for phpunit, so it might be stupid though ....
I google around but not found.
This is my code and I have multiple API and URL to test.
namespace Acme\TopBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$client = static::createClient();
echo ("first test");
$crawler = $client->request('GET', '/api/getplaceinfo');
$this->assertTrue($client->getResponse()->isSuccessful());
echo ("second test");
echo('test :' + '/api/getmetainfo/kibichuo');
$crawler = $client->request('GET', '/api/getcat');
$this->assertTrue($client->getResponse()->isSuccessful());
echo ("third test");
$crawler = $client->request('GET', '/admin/dashboard');
$this->assertTrue($crawler->filter('html:contains("My Server")')->count() > 0);
}
}
then I test like this (I am using symfony2 framework)
whitebear$ phpunit -c app/
PHPUnit 4.8.35 by Sebastian Bergmann and contributors.
.0
Time: 3.69 seconds, Memory: 109.25MB
OK (1 test, 7 assertions)
There is no message I expected by echo("first test").
So, even error happens, I can't tell which url shows the error.
My basic idea is wrong??
You should write one test for each test and in assertTrue you can put a message there.
Example:
public function testThirdTest() {
$client = static::createClient();
$crawler = $client->request('GET', '/admin/dashboard');
$this->assertTrue($crawler->filter('html:contains("My Server")')->count() > 0, 'third test goes wrong, put message here');
}
In your test you can now see the test what goes wrong (the message in assertTrue) and see, what test is failed (the name of the test).
Hope, this helps....
Related
In my functional test of my symfony 4 application, i use the Chrome Webdriver with PANTHER_NO_HEADLESS=1 to see what happen.
My problem is : Chrome browser starting with Debug Tool (F12) and not in full screen.
This is a problem because i want to test elements that appears only on full screen.
My test :
public function testMyTest()
{
$client = Client::createChromeClient();
$crawler = $client->request('GET', 'http://example.com/form');
$form = $crawler->selectButton('valider')->form([
'formField' => 'value'
]);
$client->submit($form)
// Some assertions here
}
Command :
$export PANTHER_NO_HEADLESS=1
Then
phpunit -c phpunitFunctional.xml --filter="testMyTest" path/to/FileTest.php
How can i start with full screen and without debug tool ?
I've finally found a solution.
I write it in case of someone has the same problem.
public function testMyTest()
{
$client = Client::createChromeClient();
$crawler = $client->request('GET', 'http://example.com/form');
$client->manage()->window()->maximize();
$form = $crawler->selectButton('valider')->form([
'formField' => 'value'
]);
$client->submit($form)
// Some assertions here
}
Also, consider the following:
$size = new WebDriverDimension(1024,10000);
$client->manage()->window()->setSize($size);
I have written an action which create a temporary file and returned it with a BinaryFileResponse and delete it after.
Something like this :
$response = new BinaryFileResponse($this->getFile($filename) );
$response->deleteFileAfterSend(true);
$response->headers->set('Content-Type', $this->getFileMimeType($filename));
return $response;
Where $filename refers to a temporary file.
It's working great, my file is sent and deleted after. But I cannot test it.
Here the summary of my test :
public function testIndex()
{
$client = static::createClient();
$crawler = $client->request('GET', '/post');
$response = $this->client->getResponse();
if($response instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse )
{
$fullpath = '/some/path/filename';
$this->assertFileEquals($fullpath, $response->getFile()->getPathname());
}
}
But during the time of the test the file has already been deleted...
jerome#api $ phpunit -c .
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
F
Time: 3.08 seconds, Memory: 30.25MB
There was 1 failure:
1) Tests\CoreBundle\Controller\ExperienceControllerTest::testAPICall
Failed asserting that file "/Users/jerome/Developpement/api/app/../var/cache/experience_file_15b5ae9bc7f668" exists.
I have found bug request on the symfony github but no solution yet.
Any idea of how I can achieve this ?
My ideas so far :
1 Remove deleteFileAfterSenddepending on the environment, but I found this solution quit ugly.
2 Stop using WebTestCase and start using cURL but I don't want to lose code coverage and it seems to be a lot of work.
I finally found a solution, I just send the file without using BinaryFileResponse.
$headers = array(
'Content-Type' => 'image/png',
'Content-Disposition' => 'inline; filename="image.png"');
return new Response(file_get_contents('myFile.png'), 200, $headers);
To delete the file after sending, just save the result of file_get_contents in a variable and delete the file, then send the response.
For testing, it's really easy :
$fileContent = file_get_contents($filepath);
$this->assertEquals($response->getContent(),$fileContent,"File content doesn't match requirement");
I am relatively new to PHP, which might well prove to be the main problem here - I get the feeling I'm missing something somewhat fundamental about PHP internals that would either make solving this straightforward, or make it glaringly obvious why I am wasting my time!...
Basically in the following Slim API code I would like the exception handling added by the excellent entomb/slim-json-api middleware to also apply to the subsequent myMiddleware. As implemented below, it only seems to handle failures generated in the route code...
(PHP v 5.4.17)
$ php composer.phar info
entomb/slim-json-api dev-master c11e001 Slim extension to implement fast JSON API's
slim/slim 2.6.2 Slim Framework, a PHP micro framework
API code:
require 'vendor/autoload.php';
use Slim\Middleware;
class myMiddleware extends Middleware
{
public function call()
{
$uri_array = explode('/', $this->app->request->getResourceUri());
$env = $this->app->environment;
if($uri_array[2] == 98) {
throw new \Exception("User $uri_array[2], you are not even welcome in middleware!");
} else {
$body = array('user_from_middleware' => $uri_array[2]);
$env['slim.input'] = json_encode($body);
}
$this->next->call();
}
}
///////////////////////////////////////////////////////////////////////////////////
$app = new \Slim\Slim();
$app->view(new \JsonApiView());
$app->add(new \JsonApiMiddleware());
$app->add(new myMiddleware());
$app->get('/user/:id', function($id) use ($app) {
if ($id == 99) {
throw new \Exception("User $id, you are not welcome!");
} else {
$body = json_decode($app->request->getBody());
$body->msg = "User $id welcome to my API!";
$app->render(200,(array) $body);
}
});
Here's a request that misses both Exceptions:
$ curl http://localhost:8082/test.php/user/1
{"user_from_middleware":"1","msg":"User 1 welcome to my API!","error":false,"status":200}
...this one fires the Exception in route, showing that the JsonApiMiddleware is working:
$ curl http://localhost:8082/test.php/user/99
{"msg":"ERROR: User 99, you are not welcome!","error":true,"status":500}
...but when this one fires the Exception in myMiddleware the API returns nothing:
$ curl http://localhost:8082/test.php/user/98
$
...and I can see from the log that the exception was definitely thrown:
[Mon Nov 7 21:54:08 2016] PHP Fatal error: Uncaught exception 'Exception' with message 'User 98, you are not even welcome in middleware!' in /path/to/test.php:14
Stack trace:
#0 /path/to/vendor/slim/slim/Slim/Slim.php(1302): myMiddleware->call()
#1 /path/to/test.php(42): Slim\Slim->run()
#2 {main}
thrown in /path/to/test.php on line 14
What am I missing? Apologies again if this is a tedious question.
Probably you should not $this->next->call() in MyMiddlware if an exception is thrown?..
class myMiddleware extends Middleware
{
public function call()
{
$uri_array = explode('/', $this->app->request->getResourceUri());
$env = $this->app->environment;
if($uri_array[2] == 98) {
throw new \Exception("User $uri_array[2], you are not even welcome in middleware!");
} else {
$body = array('user_from_middleware' => $uri_array[2]);
$env['slim.input'] = json_encode($body);
$this->next->call(); // call next callable only if exception was not thrown
}
}
}
Seems like you're using Slim v 2., but this is what I'd do in Slim 3.5.*
I am trying to assign a value to a variable inside the first testing function and then use it in other testing functions inside the class.
right now in my code the second function fails due to this error:
1) ApiAdTest::testApiAd_postedAdCreated
GuzzleHttp\Exception\ClientException: Client error: 404
and i dont know why. this is how the code looks like:
class ApiAdTest extends PHPUnit_Framework_TestCase
{
protected $adId;
private static $base_url = 'http://10.0.0.38/adserver/src/public/';
private static $path = 'api/ad/';
//start of expected flow
public function testApiAd_postAd()
{
$client = new Client(['base_uri' => self::$base_url]);
$response = $client->post(self::$path, ['form_params' => [
'name' => 'bellow content - guzzle testing'
]]);
$data = json_decode($response->getBody());
$this->adId = $data->id;
$code = $response->getStatusCode();
$this->assertEquals($code, 200);
}
public function testApiAd_postedAdCreated()
{
$client = new Client(['base_uri' => self::$base_url]);
$response = $client->get(self::$path.$this->adId);
$code = $response->getStatusCode();
$data = json_decode($response->getBody());
$this->assertEquals($code, 200);
$this->assertEquals($data->id, $this->adId);
$this->assertEquals($data->name, 'bellow content - guzzle testing');
}
in the phpunit doumintation https://phpunit.de/manual/current/en/fixtures.html i see i can define a
a variable inside the setUp method and then use it as i want but in my case i only know the value after the first post executes. any idea how can i use $this->adId in the second function??
Unit tests by definition should not rely on one another. You will end up with unstable and fragile tests which are then hard to debug the moment they start failing, since the cause is in another test case.
There is no guarantee in which order the tests execute in PHPUnit by default.
PHPUnit supports the #depends annotation to achieve what you want, the docs have the same warning though.
I wrote a test for a controller that saves in the database some data passed by a form.
I wrote the following test method to be sure that if the form is empty an exception is thrown:
public function testRegisterNewMerchantExceptionNoDataSubmitted()
{
$client = static::createClient();
$crawler = $client->request('GET', '/getstarted');
$form = $crawler->selectButton('getStarted[submit]')->form();
$form['getStarted[email]'] = '';
$this->setExpectedException('DomainException');
$client->submit($form);
$this->assertEquals(500, $client->getResponse()->getStatusCode());
//dump($client->getResponse());die;
}
The method i'm testing is the following:
public function endAction(Request $request)
{
$form = $this->createForm(new GetStartedType());
$form->handleRequest($request);
if ($form->isValid()) {
// Get data from form
$data = $form->getData();
} else {
throw new \DomainException('No data submitted.');
}
...
I'm sure that also during tests the exception is thrown because dumping the Response object the page is a 500 error reporting the exact message "No data submitted". More, the assertEquals test on the status code is successful, so there are no doubts that the exception is correctly thrown.
But the $this->setExpectedException() test doesn't intercept it and returns a fail of the test.
Any idea about why this happens?
Using $this->setExcpectedException() tells PHPUnit to expect the given exception type to be thrown from the test method, not just that an exception of that type is thrown at some point during execution.
When you throw an exception in a controller method, the Symfony controller catches
that exception and creates a 500 response. This means the exception will not be thrown from the test method, so the test fails. Your test looks reasonable otherwise, so removing $this->setExpectedException() should solve the problem and test the behavior you intended.