【问题标题】:PHP unit only checks the first testPHP 单元只检查第一个测试
【发布时间】:2018-03-13 12:37:12
【问题描述】:

我正在运行 Laravel,在尝试自动化开发时出现问题。我有以下测试:

class SubmitSurvivorTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */

    //Test for submit with missing parameters
    public function testEmptySubmit()
    {
        $response = $this->get('/submit/survivor');
        $response->assertSee('422');
    }

    //Test for submit with complete parameters
    public function testCorrectSubmit()
    {
        $response = $this->get('/submit/survivor?name=Jhon+Doe&age=22&gender=m&latitude=0&longitude=0&water=6&food=4&medicine=9&ammo=4');
        $response->assertSee('666');
    }
}

第一个应该返回 true,因为如果我去 /submit/survivor 我会得到 ​​p>

{"status":"422","message":"The request could not be delivered since it's missing one or more paramters"}

第二个应该返回 false,因为我得到了

{"status":"204","message":"Created successfully"}

但第二个仍然返回 true。无论我在第二个 assertSee 中输入的值如何,运行 phpunit 总是给我 0 次失败。对于其他所有测试也是如此,在我看来,它只是在验证第一种方法。

我试过改成

public function testEmptySubmit()
{
    $response = $this->get('/submit/survivor');
    $response->assertSee('422');
    $asd = $this->get('/submit/survivor?name=Jhon+Doe&age=22&gender=m&latitude=0&longitude=0&water=6&food=4&medicine=9&ammo=4');
    $asd->assertSee('666');
}

仍然没有失败,但是如果我更改第一个中的值,我仍然会失败。

改顺序好像没啥影响,我把testCorrectSubmit改到testEmptySubmit上面还是不行。

如果我在第二个中将其更改为 assertDontSee,它会失败,即使它应该返回 true,错误也太大,甚至无法放入我的终端,但类似于

[A ton of lines with html,js and stuff i can't identify]
</script>\n
</body>\n
</html>\n
' does not contain "666".

C:\xampp\htdocs\mysurvivorapi\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:331
C:\xampp\htdocs\mysurvivorapi\tests\Feature\submitSurvivorTest.php:27

FAILURES!
Tests: 6, Assertions: 6, Failures: 1.

我什至看不到“无法断言”,但我只是假设它在那里

使用 assertSeeText 似乎和

一样奇怪
public function testCorrectSubmit()
    {
        $response = $this->get('/submit/survivor?name=Jhon+Doe&age=22&gender=m&latitude=0&longitude=0&water=6&food=4&medicine=9&ammo=4');
        $response->assertSeeText('Jhon');
    }

不返回错误,但如果我将“Jhon”更改为“666”,即使它们都不在页面中也会返回错误

根据文档,它应该是这样的

public function testCorrectSubmit()
    {
        $response = $this->get('/submit/survivor',[
            'name' => 'Jhon Doe',
            'age' => '22',
            'gender' => 'm',
            'latitude' => '0',
            'longitude' => '0',
            'water' => '6',
            'food'=>'4',
            'medicine' =>'9',
            'ammo' => '4']);
        $response->assertSeeText('Jhon');
    }

部分起作用,它返回

Failed asserting that '{"status":"422","message":"The request could not be delivered since it's missing one or more paramters"}' contains "Jhon".

这表明它正在发出请求,但没有发送 GET 参数。

我从@Spacemudd 完成了第 3 步之前的所有操作,因为我不知道如何执行第 4 步,现在它正在发送 GET 参数,因为现在 Jhon Doe 出现在数据库中。但是现在 phpunit 正在返回

C:\xampp\htdocs\mysurvivorapi>php vendor/phpunit/phpunit/phpunit
PHPUnit 7.0.2 by Sebastian Bergmann and contributors.

.{"status":"204","message":"Created successfully"}

就是这样,没有失败,好吧,没有,但是如果我去幸存者表,我可以看到 Jhon Doe 被插入,我想这是一种改进?

事实证明它按预期工作。最后一个奇怪的行为是由于我有其他测试与 testCorrectSubmit 一样错误。删除它们解决了问题,现在我将正确地重写。

事实证明我又错了,似乎即使结构正确并且没有其他测试测试完整提交失败。我删除了所有测试,使用 php artisan make:test submitSurvivorTest 创建了一个新测试,如下所示

<?php

namespace Tests\Feature;

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

class submitSurvivorTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testSubmitEmpty()
    {
        $route = route('submit.survivor');
        $response = $this->get($route);
        $response->assertSee('422');
    }
    public function testSubmitComplete()
    {
        $route = route('submit.survivor', [
            'name' => 'Jhon Doe',
            'age' => '22',
            'gender' => 'm',
            'latitude' => '0',
            'longitude' => '0',
            'water' => '6',
            'food'=> '4',
            'medicine' => '9',
            'ammo' => '4',
        ]);
        $response = $this->get($route);
        $response->assertStatus(200);
    }
}

我已将名称放入我的路线文件中,它看起来像这样:

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

//Go to Index
Route::get('/', 'Controller@goHome');

//Submit a new Survivor
Route::name('submit.survivor')->get('/submit/survivor', 'SurvivorsController@submit');

//See a survivor, if no survivor id is submited sees all registered survivors
Route::name('request.survivors')->get('/request/survivors', 'SurvivorsController@getSurvivors');

//See statistics from the survivors, like average water per survivor for example.
Route::name('request.survivors.reports')->get('/request/survivors/reports', 'SurvivorsController@getReportsSurvivors');

//Update a survivor location
Route::name('update.survivor.location')->get('/update/survivor/location', 'SurvivorsController@updateSurvivorLocation');

//Flag a survivor as contaminated
Route::name('update.survivor.flag')->get('/update/survivor/flag', 'LogsController@submitFlag');

//Trade items between survivors
Route::name('update.survivors.trade')->get('/update/survivor/trade', 'TradesController@submitTrade');

而我的提交方法很简单

public function submit(Request $request){

        //Check if the required variables where sent, and if no it'll return an error
        $validator = Validator::make($request->all(), [
            'name'      =>  'required',
            'age'       =>  'required',
            'gender'    =>  'required',
            'latitude'  =>  'required',
            'longitude' =>  'required',
            'water'     =>  'required',
            'food'      =>  'required',
            'medicine'  =>  'required',
            'ammo'      =>  'required'
        ]);

        if ($validator->fails()) {
            $result = array('status' => '422', 'message' => 'The request could not be delivered since it\'s missing one or more paramters');
            echo json_encode($result);
        }

        //Create a new survivor
        $survivor = new Survivor;
        $survivor->name = $request->input('name');
        $survivor->age = $request->input('age');
        $survivor->gender = $request->input('gender');
        $survivor->latitude = $request->input('latitude');
        $survivor->longitude = $request->input('longitude');
        $survivor->water = $request->input('water');
        $survivor->food = $request->input('food');
        $survivor->medicine = $request->input('medicine');
        $survivor->ammunition = $request->input('ammo');

        //Save survivor
        $survivor->save();

        //Set the success message
        $result = array('status' => '204', 'message' => 'Created successfully');

        //Save the change into the logs and display the result
        app( 'App\Http\Controllers\LogsController')->submitLog($survivor->id,$survivor->id,"register",$result);
        exit();
    }

所有功能都直接在浏览器中运行,它们只是不适用于自动化测试。

目前运行返回

C:\xampp\htdocs\mysurvivorapi>php vendor/phpunit/phpunit/phpunit
PHPUnit 7.0.2 by Sebastian Bergmann and contributors.

..Array{"status":"204","message":"Created successfully"}

并且通过使用 --testdox-html 在我看来它甚至在显示第一个测试的结果之前就停止了它的执行,这工作正常

似乎使用--process-isolation 运行可以避免崩溃并且测试执行得很好。我已将所有 echo $response 更改为返回,因为这样似乎更好。现在它验证 emptySubmit 但不验证 completeSubmit

现在通过删除 exit() 测试在没有--process-isolation 的情况下运行并返回 断言 '' 包含“204”失败。

C:\xampp\htdocs\mysurvivorapi\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:253
C:\xampp\htdocs\mysurvivorapi\tests\Feature\submitSurvivorTest.php:36

FAILURES!
Tests: 4, Assertions: 4, Failures: 1.

但这是否已通过制作得到解决,因此响应直接在提交方法中返回,而不是在日志中。现在它似乎工作正常,因为它现在根据验证返回响应。我将开发其余的自动化测试,看看问题是否再次出现。

【问题讨论】:

    标签: laravel-5 phpunit


    【解决方案1】:
    1. 确保您的larvel.log 在完成测试后没有显示任何异常。

    1. 确保您调用的路由不在中间件auth 下,在这种情况下,您必须在调用路由之前对用户进行身份验证。

    $response = $this-&gt;actingAs($user)-&gt;get('/submit/survivor');

    $user 可以是您的 User 模型类的实例。


    1. 考虑使用辅助命令 route() 来构建 URL。

    在您的web.php 中,为您的路线添加一个名称,例如

    Route::name('survivors.submit')-&gt;get('survivors/submit', 'SurvivorsController@store');

    在你的测试中,它会变成这样:

    $route = route('survivors.submit', [
                'name' => 'Jhon Doe',
                'age' => '22',
                'gender' => 'm',
                'latitude' => '0',
                'longitude' => '0',
                'water' => '6',
                'food'=> '4',
                'medicine' => '9',
                'ammo' => '4',
              ]);
    
    $response = $this->get($route);
    

    1. 在提交控制器/函数中使用dd();,然后运行测试。这将帮助您确定问题的确切位置。

    例如,为了确保您收到正确的会话数据,您可以致电 dd(request()-&gt;except('_token'));

    【讨论】:

    • 如果您愿意多看一点,我已经添加了更多信息
    • @MatheusD.Lima 我对您代码中的exit(); 感到困惑。你能把它删除并测试..你的测试吗? ?
    • 哪一个?全部?
    • @MatheusD.Lima 是的。我相信函数最后不应该有exit();。函数结束后总会有代码在运行。
    • @MatheusD.Lima 不要使用echo,始终使用return。做return $result;.
    猜你喜欢
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    相关资源
    最近更新 更多