使用无脂肪框架进行单元测试

Posted

技术标签:

【中文标题】使用无脂肪框架进行单元测试【英文标题】:Unit Testing with Fat-Free-Framework 【发布时间】:2017-11-02 23:31:42 【问题描述】:

有没有办法使用 phpUnit,其中我有一个带有 indexTest.php 的测试文件夹,用于测试我的 index.php 文件中的路由?

无脂肪指南提供了用于模拟路由请求和 POSTS 的代码 sn-ps。如果我直接在我的测试文件中生成带有任何功能的路由,我只能设法让这样的测试工作。

我想要的是用令牌模拟一个路由,允许它从 index.php 中的路由运行并通过控制器并测试应该通过运行路由设置的 f3 变量。

<?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
    

我不想像这样声明整个路线,也许我完全错了,这是不可能的?上面的代码运行 vendor/bin/phpunit。在这方面很难找到相关的例子和教程。

【问题讨论】:

【参考方案1】:

简答

将控制器代码与引导和路由代码分开

在您的环境中重用路由配置,例如网站、CLI 和测试环境

在你的测试中使用Base-&gt;mock()来模拟之前定义的路由

不要在测试环境中执行Base-&gt;run()


长答案

我打算写一篇关于测试F3路线的文章,但由于时间不够,我在这里只给出一些观点:

    创建一个定义路由的可重用文件(例如,routes.php 文件或带有路由定义的 INI 文件)

    在运行测试代码之前加载路由。这可以通过 PHPUnit 的自定义引导文件轻松完成(--bootstrap &lt;FILE&gt; 或使用 PHPUnit 配置中的相应指令)。

    编写 PHPUnit 测试

示例

下面的例子是我GitHub Gist的改编:

bootstrap-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'));
    

一些注意事项:

bootstrap-test.php 是 PHPUnit 的自定义引导文件

bootstrap-website.php 是网站的引导文件

bootstrap-shared.php 包含所有环境共享的信息。该文件可能包括路由信息。我把例子中的路由信息​​分开了:routes.php

ExampleTest.php 是一个常规的 PHPUnit 测试

$f3-&gt;set('QUIET', true); sn-p 应添加到自定义引导文件中。引入一个变量来显示应用程序正在测试模式下运行也是一个好主意,例如$f3-&gt;set('APP.TEST', true)

F3 不会清理测试/模拟之间的变量。您可以在运行测试之前存储原始状态,然后在 PHPUnit 的 setUp() 方法中恢复状态

除了渲染页面之外,可能只收集应该可用于渲染的数据就足够了。在这种情况下,请在视图中使用引入的 APP.TEST 变量来跳过渲染

以后答案更新的注意事项

ini_set('error_log','./phpunit/error.log') $f3-&gt;set('ONERROR',function());

【讨论】:

以上是关于使用无脂肪框架进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

JAVA单元测试

JAVA单元测试

实验五 单元测试

实验五 单元测试

使用 moq 对实体框架进行单元测试

在 Windows 上使用哪个单元测试框架进行 C 开发? [关闭]