当前位置:网站首页>[laravel series 7.9] test

[laravel series 7.9] test

2022-06-24 22:58:00 Ma Nong Lao Zhang ZY

test

Test related content is not my strong point , After all, I haven't had much contact with daily development , But don't tell me , I always feel like I'm missing something , So this one is just a simple demonstration , There is no way to take you to further study .

It's amazing , Working for more than ten years , I have never experienced a company that has used test driven development , Even unit tests have never been written at work . The benefits of testing are needless to say , Hearsay also knows the benefits of test driven development , It is also expected to be applied in the follow-up work . ad locum , I also hope you can try to find a larger one , Develop more formal companies , Similar development patterns or test related knowledge can be learned more .

Run the test

Laravel Test components for , Mainly depends on PHPUnit Unit test components . This thing can be taken out alone to produce a series . I have seen it before , But as I said above , No actual project experience , So I forgot after reading it . If you have a deeper understanding of this area , In fact, you don't have to read today's content .

Because it uses PHPUnit , So we can pass PHPUnit To perform tests , For example, the following command .

vendor/bin/phpunit

But its report format is original PHPUnit Format , stay Laravel In the frame , We prefer to use a test command that comes with the framework .

php artisan test

By tracking debugging , We will find that the code of this command is in vendor/nunomaduro/collision/src/Adapters/Laravel/Commands/TestCommand.php In file , You can see from the path that , It is not included in the default vendor/laravel In the catalog . Continue to track its run() Method , find vendor/symfony/process/Process.php Medium start() Method . In this method , If you are a breakpoint debugger , You can see that it combines a command line statement , That is to say $commandline .

public function start(callable $callback = null, array $env = [])
{
    if ($this->isRunning()) {
        throw new RuntimeException('Process is already running.');
    }

    $this->resetProcessData();
    $this->starttime = $this->lastOutputTime = microtime(true);
    $this->callback = $this->buildCallback($callback);
    $this->hasCallback = null !== $callback;
    $descriptors = $this->getDescriptors();

    if ($this->env) {
        $env += $this->env;
    }

    $env += $this->getDefaultEnv();

    if (\is_array($commandline = $this->commandline)) {
        $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline));

        if ('\\' !== \DIRECTORY_SEPARATOR) {
            // exec is mandatory to deal with sending a signal to the process
            $commandline = 'exec '.$commandline;
        }
    } else {
        $commandline = $this->replacePlaceholders($commandline, $env);
    }

    if ('\\' === \DIRECTORY_SEPARATOR) {
        $commandline = $this->prepareWindowsCommandLine($commandline, $env);
    } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) {
        // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
        $descriptors[3] = ['pipe', 'w'];

        // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
        $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
        $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';

        // Workaround for the bug, when PTS functionality is enabled.
        // @see : https://bugs.php.net/69442
        $ptsWorkaround = fopen(__FILE__, 'r');
    }

    $envPairs = [];
    foreach ($env as $k => $v) {
        if (false !== $v) {
            $envPairs[] = $k.'='.$v;
        }
    }

    if (!is_dir($this->cwd)) {
        throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd));
    }

    $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);

    if (!\is_resource($this->process)) {
        throw new RuntimeException('Unable to launch a new process.');
    }
    $this->status = self::STATUS_STARTED;

    if (isset($descriptors[3])) {
        $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
    }

    if ($this->tty) {
        return;
    }

    $this->updateStatus(false);
    $this->checkTimeout();
}

This $commandline What is it ?

'/usr/local/Cellar/php/7.3.9_1/bin/php' 'vendor/phpunit/phpunit/phpunit' '--configuration=/Users/zhangyue/MyDoc/ Blog posts /LearnLaravel/learn-laravel/phpunit.xml' '--printer=NunoMaduro\Collision\Adapters\Phpunit\Printer'

Neither surprise nor surprise ? The end result is still PHPUnit Command line for automated testing . But here the framework helps us to call , And the execution result is encapsulated and returned .

Okay , Now let go of your breakpoint and continue .Laravel The default is to bring some test cases , You can see that some tests have been successful , Some tests failed . Next , We define a test ourselves .

unit testing

Unit tests are used to test whether the results of a method meet our expectations . In most cases , For our developers, if we are testing a development driven company , Unit tests must be written , And it is the most important test content . So what do unit tests usually measure ? It doesn't mean that any method should be unit tested , What needs to be tested most is actually some function functions or class methods related to the core business logic . These are more theoretical , Of course, it also depends on the individual and the company , We don't go deep into , Let's take a look at how to use the framework for unit testing .

First , We need to have a method to test , You can create a new class at will , Or use an existing class , I'm going to use the one we created before Model , Add a method directly to it .

class MTest extends Model
{
    public static function testCulAdd($a, $b){
        return $a+$b;
    }
}

This is just a demonstration , Not that you can only test static methods . This method implements a simple function , Add two parameters . Then we need to create a test class , You can use the following command line to implement .

php artisan make:test CulTest --unit

After executing the command , Will be in tests/Unit Create one in the directory CulTest.php file . Next, write the test in this file .

class CulTest extends TestCase
{
    public function test_example()
    {
        $this->assertEquals(3, MTest::testCulAdd(1, 2));
    }

    public function test_example1()
    {
        $this->assertEquals(4, MTest::testCulAdd(1, 2));
    }
}

We define two test methods , Pay attention to test_ start . We use both methods assertEquals() Assertion , This function means that the results of two parameters are equal , Just go back to true , That is, the results of the test method should be consistent with the results we expect . It's obvious that , The first test method should be passable , The second method can be problematic . So let's run it php artisan test See what the result is .

f30bc04b9936185bb6491a8f85378e8e.png


The result is in line with our expectation , The whole test case failed , That's because one of the test methods failed the assertion . About unit tests and assertions and other related information , You can refer to official documents or PHPUnit Documents , Not much here , Continue to look at other test methods .

HTTP test

HTTP A test is a mock request , It can help us directly test the page or interface . Does it feel strong . establish HTTP Tests can also use the command line .

php artisan make:test ZyBlogTest

Yes , You read that right , The difference between unit test class and unit test class is that you don't need to add the following one --unit 了 . That is to say , Actually Laravel By default, the framework wants us to use more of this HTTP The test of . Okay , Let's simply test .

class ZyBlogTest extends TestCase
{
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function test_example()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }

    public function test_example2()
    {
        $response = $this->post('/test/post');

        $response->assertStatus(200);
        $response->dump();

    }

    public function test_example3()
    {
        $response = $this->postJson('/test/post/json');

        $response->assertStatus(200)->assertJson(['a'=>1]);
    }

    public function test_example4()
    {
        $view = $this->view('test.test', ['message'=>'ZyBlog']);
        $view->assertSee("ZyBlog");
    }
}

The first test is the homepage of direct test , We assert that as long as we return 200 That's all right. . I'm going to use it directly here get() The method can be completed get request . The second test is a simple post test , We go through dump() Printed out post Output content . Of course , You can also use assertions to determine whether the test content meets our requirements , For example, the third test , We test json Whether the data returned by the interface meets the requirements . ad locum , It also shows the effect of chain call .

The test related to the last page is more fun , You just need to create a page like this .

// resources/views/test/test.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{
    {$message}}
</body>
</html>

There is no need to route , No controller required , You can test it directly . The test results are shown in the figure .

809e1fddf5490eb019217e9b2ad48485.png


Test command line scripts

Command line test is to test whether our command line script function is normal . Before the test , We need to prepare two command-line scripts first . Simplicity , Use the routing command line directly , That is to say routes/console.php Define two command line scripts directly in . This thing has not been mentioned before , However, we can understand what it is for by demonstrating here .

// routes/console.php
Artisan::command('testconsole', function () {
    $this->line("Hello ZyBlog");
});

Artisan::command('question', function () {
    $food = $this->choice(' Choose lunch ', [
        ' noodles ',
        ' Cover rice ',
        ' Hot pot ',
    ]);

    $this->line(' Your choice is :'.$food);
});

The first command line , Output a paragraph of text directly . The second is the interactive command line , You will be prompted to choose lunch , Then return to your selection . You can run it directly php artisan testconsole perhaps php artisan question Look at the effect .

then , Let's write a test script for these two command lines , You can continue to write in ZyBlogTest in .

public function test_console1(){
    $this->artisan('testconsole')->expectsOutput("Hello ZyBlog")->assertExitCode(0);
}

public function test_console2(){
    $this->artisan('question')
        ->expectsQuestion(" Choose lunch ", " noodles ")
        ->expectsOutput(" Your choice is : noodles ")
        ->doesntExpectOutput(" Your choice is : Cover rice ")
        ->assertExitCode(0);
}

The first test assertion is simple , The expected output is the string we give , Then the command line exit code is 0 That's all right. . Because we didn't do anything else , So the exit code for normal command line exit will be 0 .

The assertion of the second test is more complex . We can use expectsQuestion() Method to simulate the contents of the selection input , And then again expectsOutput() Assert the expected output , In addition, a doesntExpectOutput() That is, the results that are not expected to be output , A series of composite assertions are used to determine the pass of the test case .

I won't take a screenshot of this test result , Obviously, it passed normally . You can modify the assertions or output them for more complex tests .

summary

Through today's learning , We learned that Laravel The test component of is actually simpler and easier to use than the one we like . After all, it helped us encapsulate , You just need to create test classes and write test case methods . At the same time, I hope I can also work with you in the actual project work . Sometimes it's not that the company doesn't need us to take care of it , This kind of good thing should be used to restrain oneself , Even if the company doesn't ask , We can also add these tests to our code to improve the quality of our code , This is where I need to reflect . Don't talk much , Let's use it .

Reference documents :

https://learnku.com/docs/laravel/8.5/testing/10415

原网站

版权声明
本文为[Ma Nong Lao Zhang ZY]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241633508132.html