composer安装和phpunit单元测试

工要善其事,必先利其器,首先我们准备的是强大开发工具IDE : PhpStorm

我们用的是最新版 phpstorm 2019.3 (网上有破解激活方法)

 安装环境:composer

官网安装教程: https://getcomposer.org/download/

windows安装composer:

最简单的方法,新建文件composer-setup.bat  编辑器打开 将下面的代码拷贝进去,双击运行,完成后目录下就会下载一个文件composer.phar

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

用 php composer.phar 命令就可以开启使用 composer之旅啦:

php composer.phar --version

 当然每次敲  php composer.phar 代码太麻烦了,有没有办法省略为 直接composer命令,可以这样做

1. 把当前目录 E:\PHPServer\phplibrary 添加到系统环境变量$PATH中:

 点击编辑,弹出窗口:

 在当前目录 E:\PHPServer\phplibrary 下 新建一个 composer.bat 文件,将下面代码拷贝进去保存即可。以后就可以直接使用composer命令了。

@php "%~dp0composer.phar" %*

 

 省去输入.bat的做法,在当前目录 E:\PHPServer\phplibrary 下 新建一个 composer 文件(无后缀名),将下面代码拷贝进去保存即可。

#!/usr/bin/env sh

# php /path/to/composer.phar $*
php `dirname $0`/composer.phar $*

 

PHP Composer各大厂商镜像全镜像地址,如果使用composer安装过程过于缓慢,可以切换为国内镜像:

https://www.cnblogs.com/phplog/articles/11297728.html

 

安装phpuinit:

官网下载安装教程: https://phpunit.de/getting-started/phpunit-8.html

几个版本的包下载地址(官网)

https://phar.phpunit.de/phpunit-8.phar

https://phar.phpunit.de/phpunit-7.phar

https://phar.phpunit.de/phpunit-6.phar

https://phar.phpunit.de/phpunit-5.phar

备用下载地址:

http://phar.phpunit.cn/phpunit-4.8.phar
http://phar.phpunit.cn/phpunit-7.0.phar
http://phar.phpunit.cn/phpunit-8.0.phar
http://phar.phpunit.cn/phpunit.phar (最新版的包)

linux安装:

wget  http://phar.phpunit.cn/phpunit-7.0.phar
chmod  +x  phpunit-7.0.phar
mv  phpunit-7.0.phar  /usr/local/bin/phpunit
phpunit  --version

windows安装:

cd E:\PHPServer\phplibrary
curl -O http://phar.phpunit.cn/phpunit.phar
# phpunit  --version

 在当前目录 E:\PHPServer\phplibrary 下 新建一个 phpunit.bat 文件,将下面代码拷贝进去保存即可。以后就可以直接使用phpunit命令了。

@php "%~dp0phpunit.phar" %*

 

省去输入.bat的做法,在当前目录 E:\PHPServer\phplibrary 下 新建一个 phpunit 文件(无后缀名),将下面代码拷贝进去保存即可。

#!/usr/bin/env sh

# php /path/to/phpunit.phar $*
php `dirname $0`/phpunit.phar $*


phpunit各个版本支持情况,可以查阅网址: http://www.phpunit.cn

 

主版本 初始版本 PHP兼容性 支持
PHPUnit 8 2019年2月1日 PHP 7.2, PHP 7.3, PHP 7.4 在2021年2月5日结束支持
PHPUnit 7 2018年2月2日 PHP 7.1, PHP 7.2, PHP 7.3 在2020年2月7日结束支持
PHPUnit 6 2017年2月3日 PHP 7.0, PHP 7.1, PHP 7.2 在2019年2月1日结束支持
PHPUnit 5 2015年10月2日 PHP 5.6, PHP 7.0, PHP 7.1 在2018年2月2日结束支持
PHPUnit 4 2014年3月7日 PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6 在2017年2月3日结束支持

PHPUnit 8于2019年2月1日发布。它将支持PHP 7.2, PHP 7.3, PHP 7.4.

 

使用 PhpStorm 调试 PHPUnit 单元测试:

 首先展示下我的运行效果:

 

首先 配置 php 运行版本(我在系统环境变量$PATH添加的是 E:\PHPServer\phpStudy_v8\Extensions\php\php7.2.9nts  (php7.2版本),所以IDE也要改成一致) :

 

 Languages & Frameworks > PHP > Test Frameworks

  点击 + 新增一个 PHPUnit Local

 

 

执行单元测试

方式1: Phpstorm方式,当前测试类右键Run即可

 

 

方式2:命令行方式,进入项目目录执行

 

 要引入命名空间文件,让其能自动加载,我们可以编写一个autoload.php , 或 Bootstrap.php ,当然文件名可以随意。

<?php
# Bootstrap.php 文件 function autoloader($dir) { spl_autoload_register(function ($
class) use ($dir) { if (class_exists($class)) { return true; } $pathPsr4 = $dir."/".strtr($class, '\\', DIRECTORY_SEPARATOR) . ".php"; if (file_exists($pathPsr4)){ include_once $pathPsr4; } return true; }); } define('BOOT_ROOT', __DIR__); autoloader(BOOT_ROOT);

创建一个单元测试文件 EmailTest.php:

<?php
# EmailTest.php 文件

namespace tests;

require_once __DIR__ . '/../Bootstrap.php';

use PHPUnit\Framework\TestCase;
use src\Email;

final class EmailTest extends TestCase
{
    public function __construct($name = null, array $data = [], $dataName = '')
    {
        parent::__construct($name, $data, $dataName);
    }

    public function testCanBeCreatedFromValidEmailAddress(): void
    {
        $this->assertInstanceOf(
            Email::class,
            Email::fromString('user@example.com')
        );
    }

    public function testCannotBeCreatedFromInvalidEmailAddress(): void
    {
        $this->expectException(\InvalidArgumentException::class);

        Email::fromString('invalid');
    }

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user2@example.com',
            Email::fromString('user@example.com')
        );
    }
}

 里面的代码 引入了autoload 的 Bootstrap文件:    require_once __DIR__ . '/../Bootstrap.php';

所以phpunit可以不指定 bootstrap选项来运行: 

phpunit tests/EmailTest.php

如果没有这句文件引用进来,就得手动指定 autoload配置了:

# 指定autoload配置:
phpunit  --bootstrap  Bootstrap.php  tests/EmailTest.php

 

用 PhpStorm 进行单元测试:

手动指定 bootstrap file :

 点击选择文件,右键菜单Debug

 或者点击工具栏上的运行按钮:

 执行结果:

 phpstorm就会自动加上phpunit运行参数来运行测试 phpunit,例如:

E:\PHPServer\phpStudy_v8\Extensions\php\php7.2.9nts\php.exe -dxdebug.remote_enable=1 -dxdebug.remote_mode=req -dxdebug.remote_port=9100 -dxdebug.remote_host=127.0.0.1 E:\PHPServer\phplibrary\phpunit.phar --bootstrap E:\Develop-Work\my-project-list\my-work-list\phpTest\Bootstrap.php --no-configuration tests\EmailTest2 E:\Develop-Work\my-project-list\my-work-list\phpTest\tests\EmailTest2.php --teamcity

 

 另外,配置 phpunit.xml  (可选),例如:

 

安装 thinkphp 5.1 :

文档: https://www.kancloud.cn/manual/thinkphp5_1/353948

composer命令执行安装:

composer create-project topthink/think=5.1.* thinkapp

执行完成:

 将生成一个目录 thinkapp

 编辑 public/index.php, 原代码:

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

// [ 应用入口文件 ]
namespace think;

// 加载基础文件
require __DIR__ . '/../thinkphp/base.php';

// 支持事先使用静态方法设置Request对象和Config对象

// 执行应用并响应
Container::get('app')->run()->send();

比如我们开发项目可能加个常量等,修改 public/index.php文件:

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

// [ 应用入口文件 ]
namespace think;

define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
define('APP_PATH', ROOT_PATH . 'application' . DIRECTORY_SEPARATOR);
define('ADDON_PATH', ROOT_PATH . 'addons' . DIRECTORY_SEPARATOR);

// 加载基础文件
require ROOT_PATH . 'thinkphp' . DIRECTORY_SEPARATOR . 'base.php';

// 支持事先使用静态方法设置Request对象和Config对象

// 执行应用并响应
Container::get('app')->run()->send();

修改 console控制台文件: think

原代码:

#!/usr/bin/env php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------

namespace think;

// 加载基础文件
require __DIR__ . '/thinkphp/base.php';

// 应用初始化
Container::get('app')->path(__DIR__ . '/application/')->initialize();

// 控制台初始化
Console::init();

修改 think 文件代码:

#!/usr/bin/env php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------

namespace think;

define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
define('APP_PATH', ROOT_PATH . 'application' . DIRECTORY_SEPARATOR);
define('ADDON_PATH', ROOT_PATH . 'addons' . DIRECTORY_SEPARATOR);

// 加载基础文件
require ROOT_PATH . '/thinkphp/base.php';

// 应用初始化
Container::get('app')->path(__DIR__ . '/application/')->initialize();

// 控制台初始化
Console::init();

创建和配置网站:

 设置伪静态:

if (!-e $request_filename) {
    rewrite  ^(.*)$  /index.php?s=/$1  last;
    break;
}

 最后浏览器访问:

 查看thinkphp 5.1的版本:

打开 thinkphp/library/think/App.php 可以看到版本号

或者通过命令查看 :

php think version

 

 配置 phpstorm :

 

 

 安装thinkphp 单元测试:

文档地址: https://www.kancloud.cn/manual/thinkphp5_1/354125

 

执行composer 命令进行安装:

composer require topthink/think-testing=2.0.*

 

成功安装后,根目录就会多出 tests文件夹和 phpunit.xml 文件

如果没有生成这两个的文件夹和文件,可以到 https://github.com/top-think/think-testing 下载示例。

执行 composer update 更新包到最新:

composer update

执行 命令 php think unit 进行单元测试:

 

在 tests 文件夹 ,右键, New > PHP Test > PHPUint Test 创建一个新的单元测试文件 NewTest.php :

 

生成的 NewTest.php 文件:

 

 新生成的 tests\NewTest.php 原代码:

<?php


use PHPUnit\Framework\TestCase;

class NewTest extends TestCase
{

}

 

编辑 tests\NewTest.php文件:

<?php
# tests/NewTest.php 文件
# 注意: NewTest 是继承 PHPUnit\Framework\TestCase, 不是继承 \think\testing\TestCase
#        所以, php think unit 也只能测试 普通的 单元测试方法, 像 $this->visit('/index/test/show')->see('show_test'); 这种就会提示找不到 visit方法
#        要想能支持 visit, see方法, 只能改继承父类方法: class NewTest extends \think\testing\TestCase

use PHPUnit\Framework\TestCase;

class NewTest extends TestCase
{
    #protected $baseUrl = 'http://www.thinkapp.com';

    public function testBasicFunctions()
    {
        $this->assertTrue(true);
        $this->assertEquals(2, 1 + 1);
        $app = new \app\index\controller\Test();
        // 假设 index/test/show 方法返回的字符串中包含 "show_test"
        $this->assertContains('show_test', $app->show());
    }

    public function testTest()
    {
        $stack = [];
        $this->assertEquals(0, count($stack));
    }

    public function testSomethingIsTrue()
    {
        $this->assertTrue(true);
    }

    public function testSum()
    {
        $obj = new \app\index\controller\Test();
        $this->assertEquals(6, $obj->testNum(2, 3));
    }

    // 测试出错代码
    public function testError()
    {
        $obj = new \app\index\controller\Test();
        $this->assertEquals(6, $obj->testError(2, 3));
    }

}

在 application/index/controller 目录下 创建一个 Test.php 文件

<?php
# application/index/controller/Test.php 文件

namespace app\index\controller;

class Test
{
    public function testNum($a, $b)
    {
        $c = $a * $b;
        return $c;
    }

    public function testError($a, $b)
    {
        $c = $a * $b;
        return $z;  // 故意写错成 $z
    }

    public function show()
    {
        return 'show_test';
    }
}

 

命令行再次执行 php think unit 进行单元测试:

 

另外thinkphp自带的测试单元方法:

在 tests 文件夹下 新建 ThinkTest.php (这个就支持的比较全面)

<?php
# tests/ThinkTest.php 文件
# 注意: ThinkTest 是继承 \think\testing\TestCase, 不是继承 \PHPUnit\Framework\TestCase
#        所以, php think unit 能支持 thinkphp 自身测试单元的 visit, see方法, 例如 $this->visit('/index/test/show')->see('show_test');
#        所有的 PHPUnit 的方法都支持。

namespace tests;

class ThinkTest extends \think\testing\TestCase
{
    protected $baseUrl = 'http://www.thinkapp.com';

    public function testBasicFunctions()
    {
        $app = new \app\index\controller\Test();
        // 假设 index/test/show 方法返回的字符串中包含 "show_test"
        $this->assertContains('show_test', $app->show());
    }

    public function testBasicExample()
    {
        $this->visit('/index/test/show')->see('show_test');
    }

}

执行 php think unit 命令后的效果:

 可单独运行phpunit命令的单元测试文件,

方法:例如在tests文件夹下 新建 UnitTest.php 文件:

<?php
# tests/UnitTest.php 文件
# 注意: UnitTest 是继承 \PHPUnit\Framework\TestCase
#        UnitTest 可以单独执行 phpunit命令测试 thinkphp 框架项目。
#        执行命令: phpunit tests/UnitTest.php


namespace tests;

use PHPUnit\Framework\TestCase;

class UnitTest extends TestCase
{
    public function __construct($name = null, array $data = [], $dataName = '')
    {

        # 几个常量定义,摘抄自 public/index.php 里的文件定义
        defined('ROOT_PATH') or define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
        defined('APP_PATH')  or define('APP_PATH', ROOT_PATH . 'application' . DIRECTORY_SEPARATOR);
        defined('ADDON_PATH') or define('ADDON_PATH', ROOT_PATH . 'addons' . DIRECTORY_SEPARATOR);

        // 引入需要的环境
        require_once ROOT_PATH . '/thinkphp/base.php';
        // 初始化 App 对象,并将 APP_PATH 指向项目的 application 目录
        //\think\App::getInstance()->path(__DIR__ . '/../application/')->initialize();
        \think\Container::get('app')->path(__DIR__ . '/../application/')->initialize();

        parent::__construct($name, $data, $dataName);
    }

    public function testSomethingIsTrue()
    {
        $this->assertTrue(false);
    }

    public function testSum()
    {
        $obj = new \app\index\controller\Test();
        $this->assertEquals(6, $obj->testNum(2, 3));
    }

    public function testError()
    {
        $obj = new \app\index\controller\Test();
        $this->assertEquals(6, $obj->testError(2, 3));
    }

}

执行 phpunit 命令进行单元测试:

phpunit tests/UnitTest.php

 

 配置编辑器:

在 文件 UnitTest.php 右键 > Debug (PHPUnit) 

 

更改默认的cmd客户端,比如更改成 Git Bash (路径:D:\Program Files\Git\bin\sh.exe)

修改: Settings > Tools > Terminal > Application settings > Shell path, 输入 D:\Program Files\Git\bin\sh.exe

 

推荐更强大的单元测试工具:codeception单元测试

请查看我的另一篇文章介绍:

phpstorm集成codeception单元测试https://www.cnblogs.com/phplog/articles/12058369.html

 

tp 3.2 的单元测试可以参考(没测试过,请自行测试):

https://www.kancloud.cn/code7/tpunit/378491

https://github.com/CODE7070/TPUNIT

 

 phpunit assert断言分类整理

布尔类型

方法名含义参数返回值
assertTrue 断言为真    
assertFalse 断言为假    

NULL类型

方法名含义参数返回值
assertNull 断言为NULL    
assertNotNull 断言非NULL    

数字类型

方法名含义参数返回值
assertEquals 断言等于    
assertNotEquals 断言不等于    
assertGreaterThan 断言大于    
assertGreaterThanOrEqual 断言大于等于    
assertLessThan 断言小于    
assertLessThanOrEqual 断言小于等于    

字符类型

方法名含义参数返回值
assertEquals 断言等于    
assertNotEquals 断言不等于    
assertContains 断言包含    
assertNotContains 断言不包含    
assertContainsOnly 断言只包含    
assertLessThanOrEqual 断言小于等于    
assertNotContainsOnly 断言不只包含    

数组类型

方法名含义参数返回值
assertEquals 断言等于    
assertNotEquals 断言不等于    
assertArrayHasKey 断言有键    
assertArrayNotHasKey 断言没有键    
assertContains 断言包含    
assertNotContains 断言不包含    
assertContainsOnly 断言只包含    
assertNotContainsOnly 断言不只包含    

对象类型

方法名含义参数返回值
assertAttributeContains 断言属性包含    
assertAttributeContainsOnly 断言属性只包含    
assertAttributeEquals 断言属性等于    
assertAttributeGreaterThan 断言属性大于    
assertAttributeGreaterThanOrEqual 断言属性大于等于    
assertAttributeLessThan 断言属性小于    
assertAttributeLessThanOrEqual 断言属性小于等于    
assertAttributeNotContains 断言不包含    
assertAttributeNotContainsOnly 断言属性不只包含    
assertAttributeNotEquals 断言属性不等于    
assertAttributeNotSame 断言属性不相同    
assertAttributeSame 断言属性相同    
assertSame 断言类型和值都相同    
assertNotSame 断言类型或值不相同    
assertObjectHasAttribute 断言对象有某属性    
assertObjectNotHasAttribute 断言对象没有某属性    

class类型

方法名含义参数返回值
assertClassHasAttribute 断言类有某属性    
assertClassHasStaticAttribute 断言类有某静态属性    
assertClassNotHasAttribute 断言类没有某属性    
assertClassNotHasStaticAttribute 断言类没有某静态属性    

文件相关

方法名含义参数返回值
assertFileEquals 断言文件内容等于    
assertFileExists 断言文件存在    
assertFileNotEquals 断言文件内容不等于    
assertFileNotExists 断言文件不存在    

XML相关

方法名含义参数返回值
assertXmlFileEqualsXmlFile 断言XML文件内容相等    
assertXmlFileNotEqualsXmlFile 断言XML文件内容不相等    
assertXmlStringEqualsXmlFile 断言XML字符串等于XML文件内容    
assertXmlStringEqualsXmlString 断言XML字符串相等    
assertXmlStringNotEqualsXmlFile 断言XML字符串不等于XML文件内容    
assertXmlStringNotEqualsXmlString 断言XML字符串不相等    

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

phpunit中相关的几个断言:

assertTrue / assertFalse   断言是否为真值还是假
assertEquals     判断输出是否和预期的相等
assertGreaterThan    断言结果是否大于某个值,同样的也有lessThan(小于), greaterThanOrEqual(大于等于),
lessThanOrEqual      (小于等于).
assertContains          判断输入是否包含指定的值
assertType                判断是否属于指定类型
assertNull                  判断是否为空值
assertFileExists         判断文件是否存在
assertRegExp           根据正则表达式判断

 

其他参数资料: 

上面单元测试实例源码已经放到Github上了: https://github.com/lajox/thinkphp-codeception-example

关于断言: https://phpunit.readthedocs.io/zh_CN/latest/

PHPUnit文档: https://phpunit.de/manual/6.5/en/writing-tests-for-phpunit.html

中文文档: http://www.phpunit.cn/getting-started.html

中文文档:http://www.phpunit.cn/manual/current/zh_cn/installation.html

https://phpunit.readthedocs.io/zh_CN/latest/index.html

https://www.cnblogs.com/martini-d/p/phpstorm-pei-zhiphpunit.html#autoid-4-1-0

 

posted @ 2019-12-17 10:32  php学习笔记  阅读(6096)  评论(0编辑  收藏  举报