Unit testing using no fat

Is there a way to use PHPUnit where I have a test folder with indexTest.php inside that checks the routes in my index.php file?

The fat-free guide gives code snippets for mocking route and POSTS requests. I was able to get such a test to work if I generate the route directly in my test file with any functionality in it.

What I would like is to mock the route with tokens, let it run from the route in index.php and through the controller, and test the f3 variables that should be set by running the route.

<?php

class indexTest extends \PHPUnit_Framework_TestCase
{
    public function test()
    {
        $f3 = Base::instance();
// Don't write to STDOUT
        $f3->set('QUIET', true);
        $f3->route('GET /path', function(){ echo 'TEXT'; });

        $this->assertNull($f3->mock('GET /path'));
        $this->assertSame('TEXT', $f3->get('RESPONSE'));

        $f3->route('GET /verify/@answer/@value',
            function($f3, $params){
                $errors = array();

                $answer = $params['answer'];
                $value = $params['value'];

                $prefix = substr($answer, 0, 3);  //pre, ans, pos
                $id = (int)substr($answer, 3);      //question id number (1, 2, 3, 4)
//$value is the input value from user

                $result = check_id($prefix, $id, $value);

                if($result !== true){
                    $errors[] = $result;
                }
                $f3->set('errors', $errors);
                return $errors;
            });

        function check_id($prefix, $id, $value)
        {
            if($prefix == 'pre' || $prefix == 'pos'){

                if($value <= 0 || $value > 180 || $value === NULL){
                    echo 'The input value of ' . $prefix . $id . ' question was out of bounds';
                    return 'The input value of ' . $prefix . $id . ' question was out of bounds';
                }else{
                    return true;
                }

            }else if($prefix == 'ans'){

                if($value < 0 || $value > 10 || $value === NULL){
                    echo 'The value of quiz ans' + $id + ' was out of bounds';
                    return 'The value of quiz ans' + $id + ' was out of bounds';
                }else{
                    return true;
                }

            }else {
                return 'The prefix does not match';
            }
        }

        $this->assertNotNull($f3->mock('GET /verify/ans1/8'));
        $this->assertEmpty($f3->get('RESPONSE')[0]);

        $this->assertNotNull($f3->mock('GET /verify/dsk4/6'));
        $this->assertSame('6', $f3->get('PARAMS.value'));
        $this->assertSame('dsk4', $f3->get('PARAMS.answer'));
        $this->assertEmpty($f3->get('RESPONSE')[0]);

        $this->assertNotNull($f3->mock('GET /verify/pre4/250'));
        $this->assertSame('The input value of pre4 question was out of bounds', $f3->get('errors')[0]);
        $this->assertNotSame('pre4', $f3->get('PARAMS.answer'));

        $f3->set('QUIET',FALSE); // allow test results to be shown later

        $f3->clear('ERROR');  // clear any errors
    }
}

      

I would rather not declare the whole route this way, maybe I am completely wrong and this is not possible? The above code is running a running provider / bin / phpunit. Relative examples and tutorials are hard to find on this one.

+3


source to share


1 answer


Short answer

  • Separate your controller code from bootstrap and routing code

  • Reuse routing configuration in your environments eg. website, CLI and test environment

  • Use Base->mock()

    in your tests to mock previously defined routes

  • Do not run Base->run()

    in a testing environment


Long answer

I plan to write a long article about testing F3 routes, but due to lack of time, I will just give a few points here:

  • Create a reusable file that defines routes (such as a file routes.php

    or a file INI

    with a route)

  • Load the routes before running the test code. This can be easily done using your own bootstrap file for PHPUnit ( --bootstrap <FILE>

    or use the appropriate directive in your PHPUnit configuration).

  • Write PHPUnit tests

Example

The following example is an adaptation of my GitHub Gist :

bootstrapping-website.php

<?php

$f3 = Base::instance();

require 'bootstrap-shared.php';

// [Custom rules only for the website here]

require 'routes.php';

$f3->run();

      



bootstrap-test.php

<?php

$f3 = Base::instance();

require 'bootstrap-shared.php';

// [Custom rules only for testing environment here]

$f3->set('QUIET', true);
$f3->set('APP.TEST', true);

require 'routes.php';

      

routes.php

<?php

/**
 * @var $f3 Base
 */

$f3->route('GET /path', function(){ echo 'TEXT'; });

      

ExampleTest.php

class ExampleTest extends PHPUnit_Framework_TestCase {
    public function test() {
        // Could also be provided by a custom base TestCase.
        $f3 = Base::instance();

        $this->assertNull($f3->mock('GET /path'));
        $this->assertSame('TEXT', $f3->get('RESPONSE'));
    }
}

      

Some notes:

  • bootstrap-test.php

    is a custom boot file for PHPUnit

  • bootstrap-website.php

    is the download file for the website

  • bootstrap-shared.php

    contains information common to all environments. The file can contain routing information. I have stripped the routing information in an example:routes.php

  • ExampleTest.php

    is a regular PHPUnit test

  • The snippet $f3->set('QUIET', true);

    must be added to the custom bootstrap file. It is also a good idea to introduce a variable to indicate that the application is running in test mode, for example$f3->set('APP.TEST', true)

  • F3 doesn't clear your variables between tests / mocks. You can save the original state before running the tests and then restore the state in the PHPUnit methodsetUp()

  • Instead of rendering the pages, it may also be sufficient to collect only the data that needs to be available for rendering. In this case, use the injected variable APP.TEST

    in your view to skip rendering

Notes for future update answers

  • ini_set('error_log','./phpunit/error.log')

  • $f3->set('ONERROR',function(){});

+6


source







All Articles