浅谈自动化测试 | 有关Assertion的这些函数,你了解吗?

931 篇文章 26 订阅
646 篇文章 0 订阅

浅谈自动化测试

自动化测试(Test automation)是近年来逐渐兴起的软件开发流程,本系列文章将藉由作者过去的开发经验,与大家分享PHP/Laravel结合自动化测试的理论与实务,希望能对初学PHPUnit及自动化测试的同学有所帮助。查看以往系列文章,请点击文首合集。

通用型 Assertion 函数

1.assertEmpty

函数签名:assertEmpty(mixed $actual[, string $message = ''])

函数说明:从字面上来解释,这个函数是用来判断第1个输入参数 $actual 是否为 Empty,PHP常见空值可参考PHP官方函数 empty() 的说明。

示例:

/**
 * Example for assertEmpty()
 * @return void
 */
public function testAssertEmpty()
{
// 七种“空”值
    $emptyArray = [];
    $emptyString = '';
    $null = null;
    $zeroInt = 0;
    $zeroFloat = 0.0;
    $zeroIntString = '0';
    $false = FALSE;

// 以下各 Assertion 皆会通过测试
    $this->assertEmpty($emptyArray);
    $this->assertEmpty($emptyString);
    $this->assertEmpty($null);
    $this->assertEmpty($zeroInt);
    $this->assertEmpty($zeroFloat);
    $this->assertEmpty($zeroIntString);
    $this->assertEmpty($false);
}

要特别注意的是, "0" 会被认定为空值,但 "0.0" 却不会,这点要小心。

2.assertEquals

函数签名:assertEquals(mixed $expected, mixed $actual[, string $message = ''])

函数说明:此函数可用以判断,第1个参数 $expected 与第2个参数 $actual,两者的值是否相等。

示例:

/**
 * Example for assertEquals()
 * @return void
 */
public function testAssertEquals()
{
    // 范例值
    $string = 'string';
    $intOne = 1;
    $intZero = 0;
    $floatOne = 1.0;
    $floatZero = 0.0;
    $array1 = [];
    $array2 = ['string'];
    $stdClass1 = new \stdClass();
    $stdClass1->a_field = 'a';
    $stdClass2 = new \stdClass();
    $stdClass2->a_field = 'a';

    // 以下各 Assertion 皆会通过测试
    $this->assertEquals('string', $string);
    $this->assertEquals(1, $intOne);
    $this->assertEquals(0, $intZero);
    $this->assertEquals(1.0, $floatOne);
    $this->assertEquals(0.0, $floatZero);
    $this->assertEquals([], $array1);
    $this->assertEquals(['string'], $array2);
    $this->assertEquals($stdClass1, $stdClass2);

    // 以下为非相同资数据型态,但会判定为相等的情况
    $this->assertEquals($intOne, $floatOne);
    $this->assertEquals($intZero, $floatZero);
}

要特别注意的是,$intOne 会被认定为与 $floatOne 相等,$intZero 与 $floatZero 也是

3.assertSame

函数签名:assertSame(mixed $expected, mixed $actual[, string $message = ''])

函数说明:此函数可用以判断,第1个参数 $expected 与第2个参数 $actual,两者数据型态与值是否相等。

示例:

/**
 * Example for assertSame()
 * @return void
 */
public function testAssertSame()
{
    // 范例值
    $string = 'string';
    $intOne = 1;
    $intZero = 0;
    $floatOne = 1.0;
    $floatZero = 0.0;
    $array1 = [];
    $array2 = ['string'];
    // 范例物件
    $stdClass1 = new \stdClass();
    $stdClass1->a_field = 'a';
    $stdClass2 = new \stdClass();
    $stdClass2->a_field = 'a';
    $stdClass3 = $stdClass2;

    // 以下各 Assertion 皆会通过测试
    $this->assertSame('string', $string);
    $this->assertSame(1, $intOne);
    $this->assertSame(0, $intZero);
    $this->assertSame(1.0, $floatOne);
    $this->assertSame(0.0, $floatZero);
    $this->assertSame([], $array1);
    $this->assertSame(['string'], $array2);

    // 以下 Assertion 会通过测试,因两者指向相同的物件参考位置
    $this->assertSame($stdClass3, $stdClass2);

    // 以下为非相同数据型态,但会判定为相等的情况
    $this->assertSame($intOne, $floatOne);
    $this->assertSame($intZero, $floatZero);

    // 以下 Assertion 将会不通过测试,因两者所指向的物件参考位置不同
    $this->assertSame($stdClass1, $stdClass2);
}

值得一提的是,与 assertEquals() 相同的是,$intOne 会被认定为与 $floatOne 相等,$intZero 与 $floatZero 也是;与 assertEquals() 不同的是,它会认定2个拥有相同属性结构的类别变量是不同的。

4.assertTrue

函数签名:assertTrue(bool $condition[, string $message = ''])

函数说明:此函数可用以判断,第1个参数是否为 TRUE 。

示例:

/**
 * Example for assertTrue()
 * @return void
 */
public function testAssertTrue()
{
    $notEmptyString = 'a';
    $notZeroInt = 1;
    $notZeroFloat = 0.1;
    $stdClass = new \stdClass();
    $true = TRUE;

    // 以下各 Assertion 皆会通过测试
    $this->assertTrue(true);
    $this->assertTrue($true);
    $this->assertTrue(1 == 1);
    $this->assertTrue(1 === 1);
    $this->assertTrue($true);

    // 以下 Assertion 将会不通过测试
    $this->assertTrue($notEmptyString);
    $this->assertTrue($notZeroInt);
    $this->assertTrue($notZeroFloat);
    $this->assertTrue($stdClass);
}

特别注意,assertTrue的第1个参数的数据型态必须是bool,代入字符串或其他数据型态都会不通过。

5.assertFalse

函数签名:assertFalse(bool $condition[, string $message = ''])

函数说明:与 assertTrue 相对,此函数可用以判断,第1个参数是否为 FALSE 。

示例:

/**
 * Example for assertFalse()
 * @return void
 */
public function testAssertFalse()
{
    $notEmptyString = 'a';
    $notZeroInt = 1;
    $zeroInt = 0;
    $notZeroFloat = 0.1;
    $zeroFloat = 0.0;
    $stdClass = new \stdClass();
    $false = FALSE;

    // 以下各 Assertion 皆会通过测试
    $this->assertFalse(false);
    $this->assertFalse($false);
    $this->assertFalse(1 > 1);
    $this->assertFalse(1 < 1);
    $this->assertFalse(1 != 1);

    // 以下 Assertion 将会不通过测试
    $this->assertFalse($notEmptyString);
    $this->assertFalse($notZeroInt);
    $this->assertFalse($zeroInt);
    $this->assertFalse($notZeroFloat);
    $this->assertFalse($zeroFloat);
    $this->assertFalse($stdClass);
}

同样要注意,assertFalse的第1个参数的数据型态必须是bool,代入字符串或其他数据型态都会不通过。

6.assertIsArray

函数签名:assertIsArray($actual[, $message = ''])

函数说明:顾名思义,此函数可用来判断第1个参数是否为 Array 型态。

示例:

/**
 * Example for assertIsArraye()
 * @return void
 */
public function testAssertIsArray()
{
    $array1 = [];
    $array2 = ['2'];
    $array3 = ['key' => 'value'];
    $collection = collect([]);

    // 以下各 Assertion 皆会通过测试
    $this->assertIsArray($array1);
    $this->assertIsArray($array2);
    $this->assertIsArray($array3);
    $this->assertIsArray($collection->toArray());

    // 以下 Assertion 将会不通过测试
    $this->assertIsArray($collection);
}

特别注意的是,当你想判定的对象可能是 Collection 时,直接代入 assertIsArray() 将导致判定不通过。

7.assertIsInt

函数签名:assertIsInt($actual[, $message = ''])

函数说明:此函数可用来判断第1个参数是否为 Int 型态。

示例:

/**
 * Example for assertIsInt()
 * @return void
 */
public function testAssertIsInt()
{
    $int1 = 0;
    $int2 = 1;
    $float1 = 0.0;
    $float2 = 1.0;
    $string1 = '0';
    $string2 = '1';

    // 以下各 Assertion 皆会通过测试
    $this->assertIsInt($int1);
    $this->assertIsInt($int2);

    // 以下 Assertion 将会不通过测试
    $this->assertIsInt($float1);
    $this->assertIsInt($float2);
    $this->assertIsInt($string1);
    $this->assertIsInt($string2);
}

8.assertIsFloat

函数签名:assertIsFloat($actual[, $message = ''])

函数说明:此函数可用来判断第1个参数是否为 Float 型态。

示例:

/**
 * Example for assertIsFloat()
 * @return void
 */
public function testAssertIsFloat()
{
    $float1 = 0.0;
    $float2 = 1.0;
    $float3 = -1.0;


    // 以下各 Assertion 皆会通过测试
    $this->assertIsInt($float1);
    $this->assertIsInt($float2);
    $this->assertIsInt($float3);
}

以上是几个通用型 Assertion 函数,有兴趣同学,可参考范例练习看看。

HTTP相关的Assertion函数

这几个函数,其使用方式和上面所介绍的略有不同。以下所列各函数,皆是基于 HTTP Response 来做验证测试,因此大家会看到 $response = $this->get('/') 像这样的语句,执行到这语句时,PHPUnit 将会执行HTTP Resquest GET / ,相当于用浏览器开启网站根网址,或是用 Postman 打网站的根网址。更多详细说明可参考此链接:https://laravel.com/docs/9.x/http-tests#introduction

除此之外,下面所提到的几个 Assertion 函数,并非 PHPUnit 内建,而是由 Laravel 所扩充,因此需注意是否有确实引用到 use Tests\TestCase ,该档通常位于 tests/ 底下:

<?php
// tests/TestCase.php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
}

Cookie & Session

1.assertCookie

函数签名:$response->assertCookie($cookieName, $value = null)

函数说明:可验证回应中是否含有 $cookieName 的 Cookie,且是否与给定的 $value 值相等。

示例:

Route:

Route::get('/assertCookie', function () {
    return response('')->withCookie('cookieName', 'cookieValue');
});

Test:

/**
 * Example for assertCookie()
 * @return void
 */
public function testAssertCookie()
{
    $response = $this->get('/assertCookie');

// 通过测试
    $response->assertCookie('cookieName', 'cookieValue');
}

2.assertCookieMissing

函数签名:$response->assertCookieMissing($cookieName)

函数说明:可验证回应中是否不含 $cookieName 的 Cookie。

示例:

Route:​​​​​​​

Route::get('/assertCookieMissing', function () {
    return response('')->withCookie('cookieName', 'cookieValue');
});

Test:

/**
 * Example for assertCookieMissing()
 * @return void
 */
public function testAssertCookieMissing()
{
    $response = $this->get('/assertCookie');

// 通过测试
    $response->assertCookieMissing('cookieName2');
}

3.assertSessionHas

函数签名:$response->assertSessionHas($key, $value)

函数说明:可验证在回应请求后,Laravel Session 储存库是否含有指定 Key 值的 Session。

示例:

Route:

Route::get('/assertSessionHas', function () {
    Session::put('sessionKey', 'sessionValue');

    return response('');
});

Test:

/**
 * Example for assertSessionHas()
 * @return void
 */
public function testassertSessionHas()
{
    $response = $this->get('/assertSessionHas');

// 通过测试
    $response->assertSessionHas('sessionKey');
}

HTTP

1.assertSuccessful、assertOk、assertNotFound、assertForbidden、assertUnauthorized、assertUnprocessable

函数签名:

$response->assertSuccessful()

$response->assertOk()

$response->assertNotFound()

$response->assertForbidden()

$response->assertUnauthorized()

$response->assertUnprocessable()

函数说明:这6个函数所验证的情境很单纯,都是验证 HTTP Status Code,细部分别如下:

assertSuccessful:回应为成功类HTTP Status Code(>= 200 and < 300)

assertOk:回应为 200 HTTP Status Code

assertNotFound:回应为 400 HTTP Status Code

assertForbidden:回应为 403 HTTP Status Code

assertUnauthorized:回应为 401 HTTP Status Code

assertUnprocessable:回应为 422 HTTP Status Code

示例:

Route:

Route::get('/notFound', function () {
    return response('', 404);
});

Route::get('/ok', function () {
    return response('', 200);
});

Route::get('/successful', function () {
    return response('', 201);
});

Route::get('/forbidden', function () {
    return response('', 403);
});

Route::get('/unauthorized', function () {
    return response('', 401);
});

Route::get('/unprocessable', function () {
    return response('', 422);
});

Test:

/**
 * Example for assertSuccessful()、assertOk()、assertNotFound()、assertForbidden()、assertUnauthorized()、assertUnprocessable()
 * @return void
 */
public function testAssertHttpStatusCode()
{
    $response1 = $this->get('/notFound');
    $response2 = $this->get('/ok');
    $response3 = $this->get('/successful');
    $response4 = $this->get('/forbidden');
    $response5 = $this->get('/unauthorized');
    $response6 = $this->get('/unprocessable');

// 以下各 Assertion 皆会通过测试
    $response1->assertNotFound();
    $response2->assertOk();
    $response3->assertSuccessful();
    $response4->assertForbidden();
    $response5->assertUnauthorized();
    $response6->assertUnprocessable();
}

2.assertJson

函数签名:$response->assertJson(array $data, $strict = false)

函数说明:此函数会验证回应是否为JSON格式,并且判断其JSON结构(包含栏位及值)是否包含给定的 $data 结构(包含栏位及值)。

示例:

Route:

Route::get('/assertJson', function () {
    return response()->json(
        [
            'field1' => 'value1',
            'field2' => 'value2',
        ]
    );
});

Test:

/**
 * Example for assertJson()
 * @return void
 */
public function testAssertJson()
{
    $response = $this->get('/assertJson');

// 通过测试
    $response->assertJson(['field1' => 'value1']);
}

3.assertJsonStructure

函数签名:$response->assertJsonStructure(array $structure)

函数说明:与前一个函数不同,此函数只验证是否含有给定的结构(不验证值)。

示例:

Route:

Route::get('/assertJsonStructure', function () {
    return response()->json(
        [
            'a' => [
                'b' => [
                    'c',
                ],
            ],
        ]
    );
});

Test:

/**
 * Example for assertJsonStructure()
 * @return void
 */
public function testAssertJsonStructure()
{
    $response = $this->get('/assertJsonStructure');


    // 通过测试
    $response->assertJsonStructure(['a' => ['b']]);
}

以上介绍的就是几个 HTTP 相关 Assertion 函数。由于 Assertion 函数实在太多,取舍之下,只能先为大家介绍最重要与最常用的几个。

数据库 、阵列Assertion函数

下面再介绍几个数据库 Assertion 函数,与阵列 Assertion 函数。以下提到的数据库 Assertion 函数,并非 PHPUnit 内建,而是由 Laravel 所扩充,因此需注意是否有确实引用到 use Tests\TestCase 。最后面介绍的2个阵列 Assertion 函数,则是PHPUnit内建的。

在介绍数据库 Assertion 函数前,要先请大家在根目录下的 phpunit.xml 的 <php> 标签内,加入以下 <env> 子标签:

<php>
    <-- ...前略...->

    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>

    <-- ...后略...->
</php>

这2个设定值,会在执行PHPUnit测试时,暂时使用 phpunit.xml 内 <env> 所设定的数据库环境变量值,以避免改变到实际数据库的数据。同时,在数据库 Assertion 函数的示例中,皆会使用到 Illuminate\Foundation\Testing\RefreshDatabase 这个 Trait。

让让我们看看吧!

数据库

1.assertDatabaseCount

函数签名:assertDatabaseCount($table, int $count, $connection = null)

函数说明:此函数可以验证,指定数据库连线下,指定数据表是否含有指定数量的数据。当没有指定数据库连线时,将会使用预设数据库连线。

示例:

<?php


namespace Tests\Feature;


use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;


class DatabaseTest extends TestCase
{
    use RefreshDatabase;


    /**
     * Example for assertDatabaseCount()
     * @return void
     */
    public function testAssertDatabaseCount()
{
        // 假设 users 数据表中有1笔数据,则以下 Assestion 将通过测试
        $this->assertDatabaseCount('users', 1);
    }
}

2.assertDatabaseHas

函数签名:assertDatabaseHas($table, array $data, $connection = null)

函数说明:此函数可以验证,指定数据库连线下,指定数据表是否含有指定数据结构与值的数据。与前一函数相同,当没有指定数据库连线时,将会使用预设数据库连线。

示例:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class DatabaseTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Example for assertDatabaseHas()
     * @return void
     */
    public function testAssertDatabaseHas()
{
        // 假设 users 数据表中至少有1条数据
        // 其 email 栏位值为 test@test.com
        // 则以下 Assestion 将通过测试

        $this->assertDatabaseHas('users', [
            'email' => 'test@test.com'
        ]);
    }
}

3.assertDatabaseMissing

函数签名:assertDatabaseMissing($table, array $data, $connection = null)

函数说明:此函数可以验证,指定数据库连线下,指定数据表是否 不 含有指定数据结构与值的数据。与前一函数相同,当没有指定数据库连线时,将会使用预设数据库连线。

示例:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class DatabaseTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Example for assertDatabaseMissing()
     * @return void
     */
    public function testAssertDatabaseMissing()
{
        // 假设 users 数据表中无任1条数据
        // 其 email 栏位值为 test@test.com
        // 则以下 Assestion 将通过测试
        $this->assertDatabaseMissing('users', [
            'email' => 'test@test.com'
        ]);
    }
}

阵列

1.assertArrayHasKey

函数签名:assertArrayHasKey($key, $array, string $message = '')

函数说明:这个函数相当单纯,可检查第2个参数中,是否含有第2个参数所述的键。

示例:

/**
 * Example for assertArrayHasKey()
 * @return void
 */
public function testAssertArrayHasKey()
{
    $array = ['key' => 'value'];

    $this->assertArrayHasKey('key', $array);
}

2.assertJsonStringEqualsJsonString

函数签名:assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = '')

函数说明:有时会需要验证结构比较复杂的关联式阵列,但PHPUnit被未提供相对应的关联式阵列 Assertion 函数,这时候便可使用此函数,将欲验证的值先做 json_encode ,代入第2参数,并将期望的关联式阵列结构与值,以JSON String的形式代入第1个参数。

示例:

/**
 * Example for assertJsonStringEqualsJsonString()
 * @return void
 */
public function testAssertJsonStringEqualsJsonString()
{
    $array = [
        'key' => 'value',
        'object1' => [
            'array' => [1, 2, 3,]
        ],
    ];

    $this->assertJsonStringEqualsJsonString(
        '{"object1":{"array":[1,2,3]},"key":"value"}',
        json_encode($array)
    );
}

以上大概介绍了20多个Assertion 函数,之后介绍运用函数撰写API自动化测试。


参考资料:

1.https://phpunit.readthedocs.io/en/9.5/assertions.html

2.https://laravel.com/docs/9.x/http-tests#available-assertions

3.https://laravel.com/docs/9.x/dusk#available-assertions

4.https://laravel.com/docs/9.x/database-testing#available-assertions

5.https://www.php.net/manual/en/function.empty.php

6.https://laravel.com/docs/9.x/http-tests

7.https://laravel.com/docs/9.x/database-testing

8.https://phpunit.readthedocs.io/en/9.5/assertions.html

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值