Install Codeception via Composer
$ composer require "codeception/codeception"
Create an alias so you do not have to write the entire path every time you execute a command:
$ alias codecept='./vendor/bin/codecept'
Create an API test suite:
$ codecept generate:suite apiEdit the configuration file tests/api.suite.yml:
class_name: ApiTester
modules:
enabled:
- \Helper\Api
- REST:
url: "http://yourwebste.com/"
depends: PhpBrowser
part: Json
I will be using "Cest" format: "Cest combines scenario-driven test approach with OOP design. In case you want to group a few testing scenarios into one you should consider using Cest format."
$ codecept generate:cest api UsersTestCestThis command is creating a PHP file under tests/api/.
Before starting to write my first tests I need to find a way to pass a username and password to all tests, as it is needed for connecting to the API.
I can add any parameters to the api.suite.yml and access them inside my test classes:
api.suite.yml
class_name: ApiTester modules: enabled: - \Helper\Api - REST: url: "http://yourwebsite.com" depends: PhpBrowser part: Json params: username: "username" password: "password"
And inside tests/api/UsersTestCest.php
class UsersTestCest { private $username; private $password; public function _before(ApiTester $I) } { $config = \Codeception\Configuration::config(); $apiSettings = \Codeception\Configuration::suiteSettings('api', $config); $this->username = $apiSettings['params']['username']; $this->password = $apiSettings['params']['password']; } }
The function "_before()" will be executed as it names says, before actual test functions, and it will initialize the variables with values from api.suite.yml file.
Let's write the first test function:
public function createUser(ApiTester $I) { $action = "create_user"; $I->haveHttpHeader('Content-Type', 'application/json'); $array=[ "action"=> $action, "username"=> $this->username, "key"=> $this->password, "user_username"=> "new_username", "user_email"=> "email@company.com", "user_password"=> "password" ] ]; $string = json_encode($array); $I->sendPOST('api.php',$string); $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200 $I->seeResponseIsJson(); $I->seeResponseMatchesJsonType([ 'operation' => 'string', 'status' => 'string', ]); }
The link where the request is sent with the function sendPost() is the concatenation between the URL parameter from api.suite.yml and the first parameter in sentPost() function.
You can check if the response has HTTP status 200, if it is in JSON format and if the JSON has the expected structure.
Even more you can create your own assertions. These custom functions needs to be added to the file "tests/_support/ApiTester.php".
I will add a function to verify if the "status" field from the response is equal to '1'
<?php namespace Helper; class will be available in $I use Codeception\TestInterface; class Api extends \Codeception\Module { public function checkOperationStatusSuccess() { $response = $this->getModule('REST')->response; $array = json_decode($response, true); $this->assertEquals('1',$array['status'],"Operation status should be '1' for success."); } }
Run all tests with this command:
codecept run api -v
Or only tests from certain class:
$ codecept run tests/api/UsersTestCest.php -v
The tests are executed in the alphabetic order of the classes, but you can use the annotation "@depends" to indicated that your test function depends on other one(s).
Enjoy!