Laravel 测试: PHPUnit 入门教程

介绍 PHPUnit 测试的基础知识,使用基本的 PHPUnit 断言和 Laravel 测试助手。

介绍

PHPUnit 是最古老和最著名的 PHP 单元测试包之一。它主要用于单元测试,这意味着可以用尽可能小的组件测试代码,但是它也非常灵活,可以用于很多不仅仅是单元测试。

PHPUnit 包含许多简单和灵活的断言允许您轻松地测试代码,当您测试特定的组件时,这些断言非常有效。但是,它确实意味着测试更高级的代码(如控制器和表单提交验证)可能会复杂得多。

为了帮助开发人员更容易地进行开发, Laravel 框架  包含了一系列 应用程序测试帮助程序 ,允许您编写非常简单的 PHPUnit 测试来测试应用程序的复杂部分。

本教程的目的是向您介绍 PHPUnit 测试的基础知识,使用默认 PHPUnit 断言和 Laravel 测试助手。这样做的目的是在本教程结束时,您可以自信地为应用程序编写基本测试。

前提

本教程假设您已经熟悉 Laravel 并知道如何在应用程序目录中运行命令(例如 php artisan 命令)。我们将创建几个基本的示例类来学习不同的测试工具如何工作,因此建议您为本教程创建一个新的应用程序。

如果已经安装了 Laravel ,则可以通过运行以下命令创建新的测试应用程序:

laravel new phpunit-tests复制代码

或者,您可以直接使用 Composer 创建新应用程序:

composer create-project laravel/laravel --prefer-dist复制代码

其他安装方法也可以在 Laravel 文档中找到。

创建一个新的测试

使用 PHPUnit 的第一步是创建一个新的测试类。测试类的约定是它们存储在应用程序目录的 ./tests/ 下。在这个文件夹中,每个测试类都被命名为 <name>Test.php 。这种格式允许 PHPUnit 查找每个测试类---它将忽略任何不以 Test.php 结尾的文件。

在新的 Laravel 应用程序中,你会注意到 ./tests/ 目录中有两个文件:  ExampleTest.php 和 TestCase.php.  TestCase.php 文件是一个引导文件用于在我们的测试中设置 Laravel 环境。这允许我们在测试中使用 Laravel Facades 并为测试助手提供框架,我们将在稍后介绍。 ExampleTest.php 是一个示例测试类,其中包含使用应用程序测试助手的基本测试用例-暂时忽略它。

要创建一个新的测试类,我们可以手动创建一个新文件,或者运行由 Laravel 提供的 Artisan 命令 make:test

为了创建一个名为 BasicTest 的测试类,我们只需要运行这个 artisan 命令:

php artisan make:test BasicTest复制代码

Laravel 将创建一个如下所示的基本测试类:

<?php
class BasicTest extends TestCase
{/*** 一个基本的测试示例。** @return void*/public function testExample(){$this->assertTrue(true);}
}复制代码

这里要注意的最重要的事情是 test 方法名称上的前缀,与 Test 类名后缀一样,这样 test 前缀告诉 PHPUnit 在测试时运行哪些方法。如果您忘记了 test 前缀,那么 PHPUnit 将忽略该方法。

在我们第一次运行测试套件之前,有必要指出 Laravel 提供的默认 phpunit.xml 文件。 PHPUnit 在运行时会自动在当前目录中查找名为 phpunit.xml 或者 phpunit.xml.dist 的文件。您可以在此处配置测试的特定选项。

这个文件中有很多信息,但是现在最重要的部分是在 testsuite 目录定义:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit ... ><testsuites><testsuite name="Application Test Suite"><directory>./tests/</directory></testsuite></testsuites>...
</phpunit>复制代码

这将告诉 PHPUnit 运行时在 ./tests/ 目录中找到的测试,正如我们之前所知,这是存储测试的约定。

现在我们已经创建了一个基本测试,并且知道了 PHPUnit 配置,现在是第一次运行测试的时候了。

您可以通过运行以下 phpunit 命令来运行测试:

./vendor/bin/phpunit复制代码

您应该看到与此类似的输出:

PHPUnit 4.8.19 by Sebastian Bergmann and contributors...Time: 103 ms, Memory: 12.75MbOK (2 tests, 3 assertions)复制代码

现在我们已经有了一个有效的 PHPUnit 设置,现在是时候开始编写一个基本测试了。

注意,它会统计2个测试和3个断言,因为 ExampleTest.php 文件包含了一个带有两个断言的测试。我们的新基本测试包括一个单独的断言,该断言已通过。

写一个基础测试

为了帮助 PHPUnit 提供的基本断言,我们将首先创建一个提供一些简单功能的基本类

在 ./app/ 目录中创建一个名为 Box.php 的新文件,并复制此示例类:

<?php
namespace App;class Box
{/*** @var array*/protected $items = [];/*** 使用给定项构造框** @param array $items*/public function __construct($items = []){$this->items = $items;}/*** 检查指定的项目是否在框中。** @param string $item* @return bool*/public function has($item){return in_array($item, $this->items);}/*** 从框中移除项,如果框为空,则为 null 。** @return string*/public function takeOne(){return array_shift($this->items);}/*** 从包含指定字母开头的框中检索所有项目。** @param string $letter* @return array*/public function startsWith($letter){return array_filter($this->items, function ($item) use ($letter) {return stripos($item, $letter) === 0;});}
}复制代码

接下来, 打开你的 ./tests/BasicTest.php 类(我们之前创建的类),并删除默认创建的 testExample 方法, 你应该留一个空类。

我们现在将使用七个基本的 PHPUnit 断言来为我们的 Box 类编写测试。这些断言是:

  • assertTrue()
  • assertFalse()
  • assertEquals()
  • assertNull()
  • assertContains()
  • assertCount()
  • assertEmpty()

assertTrue() 和 assertFalse()

assertTrue() 和 assertFalse() 允许你声明一个值等于 true 或 false 。这意味着它们非常适合测试返回布尔值的方法。在我们的 Box 类中,我们有一个名为 has($item) 的方法,当指定的项在 box 中或不在 box 中时,该方法返回对应返回 true 或 false .

要在 PHPUnit 中为此编写测试,我们可以执行以下操作:

<?php
use App\Box;class BasicTest extends TestCase
{public function testHasItemInBox(){$box = new Box(['cat', 'toy', 'torch']);$this->assertTrue($box->has('toy'));$this->assertFalse($box->has('ball'));}
}复制代码

注意我们如何只将一个参数传递给 assertTrue() 和 assertFalse() 方法,并且它是 has($item) 方法的输入.

如果您现在运行 ./vendor/bin/phpunit 命令,您会注意到输出包括:

OK (2 tests, 4 assertions)复制代码

这意味着我们的测试已经通过。

如果您将 assertFalse() 替换成 assertTrue() 并运行 phpunit 命令,输出将如下所示:

PHPUnit 4.8.19 by Sebastian Bergmann and contributors.F.Time: 93 ms, Memory: 13.00MbThere was 1 failure:1) BasicTest::testHasItemInBox
Failed asserting that false is true../tests/BasicTest.php:12FAILURES!
Tests: 2, Assertions: 4, Failures: 1.复制代码

这告诉我们第12行的断言未能断言 false 值是 true - 因为我们将 assertFalse() 替换为 assertTrue()

将其交换回来,然后重新运行 PHPUnit 。测试应该再次通过,因为我们已经修复了破损的测试。

assertEquals() 与 assertNull()

接下来,让我们看看 assertEquals(), 以及 assertNull()

assertEquals() 用于比较变量实际值与预期值是否相等。我们用它来检查 takeOne() 方法的返回值是否为 Box 内的当前值。当 Box 为空时,takeOne() 将返回 null,我们亦可使用 assertNull() 来进行检查。

与 assertTrue()assertFalse() 以及 assertNull() 不同,assertEquals() 需要两个参数。第一个参数为 预期 值,第二个参数则为 实际 值。

可参照如下代码实现以上断言(assertions):

<?php
use App\Box;class BasicTest extends TestCase
{public function testHasItemInBox(){$box = new Box(['cat', 'toy', 'torch']);$this->assertTrue($box->has('toy'));$this->assertFalse($box->has('ball'));}public function testTakeOneFromTheBox(){$box = new Box(['torch']);$this->assertEquals('torch', $box->takeOne());// 当前 Box 为空,应当为 Null$this->assertNull($box->takeOne());}
}复制代码

运行 phpunit 命令,你应当看到如下输出:

OK (3 tests, 6 assertions)复制代码

assertContains() 和 assertCount() 以及 assertEmpty()

终于,我们有三个作用于数组有关的断言,我们能够使用它们去检查 Box 类中的  startsWith($item) 方法。 assertContains() 断言传递进来的数组中包含指定值, assertCount() 断言数组的项数为指定数量,assertEmpty() 断言传递进来的数组为空。

让我们来执行以下测试:

<?php
use App\Box;class BasicTest extends TestCase
{public function testHasItemInBox(){$box = new Box(['cat', 'toy', 'torch']);$this->assertTrue($box->has('toy'));$this->assertFalse($box->has('ball'));}public function testTakeOneFromTheBox(){$box = new Box(['torch']);$this->assertEquals('torch', $box->takeOne());// Null,现在这个 box 是空的。$this->assertNull($box->takeOne());}public function testStartsWithALetter(){$box = new Box(['toy', 'torch', 'ball', 'cat', 'tissue']);$results = $box->startsWith('t');$this->assertCount(3, $results);$this->assertContains('toy', $results);$this->assertContains('torch', $results);$this->assertContains('tissue', $results);// 如果传递复数断言数组为空$this->assertEmpty($box->startsWith('s'));}
}复制代码

保存并再一次运行你的测试:

OK (4 tests, 9 assertions)复制代码

恭喜你,你刚刚使用七个基础的 PHPUnit 断言完成了对 Box 类的全部测试。通过这些简单的断言你能够做许多事,对于其他断言,大多数要更复杂,不过它们仍遵循以上使用规则。

测试你的程序

在你的程序里,对每个组件进行单元测试在很多情况下都是有必要的,而且也应该成为你开发过程中必不可少的一部分,但这并不是你需要做的全部的测试。当你构建一个包含复杂视图、导航和表单的程序时,你同样想测试这些组件。这时,Laravel的测试助手可以使这些测试像单元测试简单组件一样容易。

我们之前查看在 ./tests/ 目录下的默认文件时跳过了 ./tests/ExampleTest.php 文件。 现在打开它,内容如下所示:

<?php
class ExampleTest extends TestCase
{/**
* 一个基本功能测试示例。
*
* @return void
*/public function testBasicExample(){$this->visit('/')->see('Laravel 5');}
}复制代码

我们可以看到这个测试示例非常简单。在不知道测试助手如何运作的情况下,我们可以猜测它的意思如下:

  1. 当我访问/ (根目录)
  2. 我应该看到 'Laravel 5'

如果你打开你的web浏览器,访问我们的程序(如果你没有启动你的web服务器,你可以运行 php artisan serve ),你应该可以在web根目录上看到屏幕上有“Laravel 5”的文本。 鉴于这个测试已经通过了PHPUnit,我们可以很确定地说我们对这个测试示例改造是正确的。

这个测试确保了访问/路径,网页可以返回“'Laravel 5”的文本。一个如此简单的检查也许不代表什么,但如果你的网站上要显示关键信息,它就可以在一个别处的改动导致这个页面无法正常显示正确的信息时,防止你部署一个被损坏的程序。

visit()、see() 以及 dontSee()

现在尝试编写自己的测试,更进一步理解它吧。

首先,编辑 ./app/Http/routes.php ,增加一个新的路由。为了教程目的,我们创建希腊字母定义的路由:

<?php
Route::get('/'function () {return view('welcome');
});Route::get('/alpha'function () {return view('alpha');
});复制代码

然后,创建视图文件 ./resources/views/alpha.blade.php,使用 Alpha 作为关键字,保存基本的HTML文件:

<!DOCTYPE html>
<html><head><title>Alpha</title></head><body><p>This is the Alpha page.</p></body>
</html>复制代码

打开浏览器,输入网址: http://localhost:8000/beta,页面会显示出 "This is the Alpha page." 的内容。

现在我们有了测试用到的模版文件,下一步,我们通过运行命令 make:test 来创建一个新的测试文件:

php artisan make:test AlphaTest复制代码

然后变成刚创建好的测试文件,按照框架提供的例子,测试 "alpha" 页面上没有包含 "beta" 。 我们可以使用方法 dontSee() ,它是 see() 的对应的反向方法。

下面代码是上面实现的简单例子:

<?php
class AlphaTest extends TestCase
{public function testDisplaysAlpha(){$this->visit('/alpha')->see('Alpha')->dontSee('Beta');}
}复制代码

保存并运行 PHPUnit (./vendor/bin/phpunit),测试代码应该会全部通过,你会看到像这样的测试状态内容显示:

OK (5 tests,12 assertions)复制代码

开发前先写测试

对于测试来说,测试驱动开发 (TDD) 是非常酷的方法,首先我们先写测试。写完测试并执行它们,你会发现测试没通过,接下来 我们编写满足测试的代码,再次执行测试,使测试通过。 接下来让我们开始。

首先,建立一个 BetaTest 类使用 make:test artisan 命令:

php artisan make:test BetaTest复制代码

接下来,更新测试用例以便检查 /beta 的路由 route 为「Beta」:

<?php
class BetaTest extends TestCase
{public function testDisplaysBeta(){$this->visit('/beta')->see('Beta')->dontSee('Alpha');}
}复制代码

现在使用 ./vendor/bin/phpunit 命令来执行测试。结果是一个看起来简洁但不好的错误信息,如下:

> ./vendor/bin/phpunit
PHPUnit 4.8.19 by Sebastian Bergmann and contributors.....F.Time: 144 ms, Memory: 14.25MbThere was 1 failure:1) BetaTest::testDisplaysBeta
一个对 [http://localhost/beta] 的请求失败了。收到状态码 [404]。...FAILURES!
Tests: 6, Assertions: 13, Failures: 1.复制代码

我们现在需要创建这个不存在的路由。让我们开始。

首先,编辑 ./app/Http/routes.php 文件来创建新的 /beta 路由:

<?php
Route::get('/', function () {return view('welcome');
});Route::get('/alpha', function () {return view('alpha');
});Route::get('/beta', function () {return view('beta');
});复制代码

接下来,在 ./resources/views/beta.blade.php 下创建如下视图模版:

<!DOCTYPE html>
<html><head><title>Beta</title></head><body><p>This is the Beta page.</p></body>
</html>复制代码

现在再一次执行 PHPUnit,结果应该再一次回到绿色。

> ./vendor/bin/phpunit
PHPUnit 4.8.19 by Sebastian Bergmann and contributors.......Time: 142 ms, Memory: 14.00MbOK (6 tests, 15 assertions)复制代码

这样我们就通过在完成新的页面之前写测试的方式,对 测试驱动开发 进行了实践。

click() 和 seePageIs()

Laravel 也提供一个辅助函数 (click()) 允许测试点击页面中存在的连接 ,以及一个方法 (seePageIs()) 检查点击展示的结果页面。

让我们使用这两个辅助函数去执行在 Alpha 和 Beta 页面的链接。

首先,我们更新我们的测试。打开 AlphaTest 类,我们将添加一个新的测试方法,这将点击 「alpha」页面上的「Next」链接跳转到 「beta」页面。

新的测试代码如下:

<?php
class AlphaTest extends TestCase
{public function testDisplaysAlpha(){$this->visit('/alpha')->see('Alpha')->dontSee('Beta');}public function testClickNextForBeta(){$this->visit('/alpha')->click('Next')->seePageIs('/beta');}
}复制代码

注意到,在我们新建的 testClickNextForBeta() 方法中,我们并没有检查每一个页面的内容。 其他测试都成功的检查了两个页面的内容,所以这里我们只关心点击 「Next」链接将发送到 /beta

你现在可以运行测试组件了,但就像预料的一样测试将不通过,因为我们还没有更新我们的 HTML。

接下来,我们将更新 BetaTest 来做类似的事情:

<?php
class BetaTest extends TestCase
{public function testDisplaysBeta(){$this->visit('/beta')->see('Beta')->dontSee('Alpha');}public function testClickNextForAlpha(){$this->visit('/beta')->click('Previous')->seePageIs('/alpha');}
}复制代码

接下来,我们更新我们的 HTML 模版。

./resources/views/alpha.blade.php

<!DOCTYPE html>
<html><head><title>Alpha</title></head><body><p>This is the Alpha page.</p><p><a href="/beta">Next</a></p></body>
</html>复制代码

./resources/views/beta.blade.php

<!DOCTYPE html>
<html><head><title>Beta</title></head><body><p>This is the Beta page.</p><p><a href="/alpha">Previous</a></p></body>
</html>复制代码

保存文件,再一次执行 PHPUnit:

> ./vendor/bin/phpunit
PHPUnit 4.8.19 by Sebastian Bergmann and contributors.F....F..Time: 175 ms, Memory: 14.00MbThere were 2 failures:1) AlphaTest::testDisplaysAlpha
Failed asserting that '<!DOCTYPE html>
<html><head><title>Alpha</title></head><body><p>This is the Alpha page.</p><p><a href="/beta">Next</a></p></body>
</html>
' does not match PCRE pattern "/Beta/i".2) BetaTest::testDisplaysBeta
Failed asserting that '<!DOCTYPE html>
<html><head><title>Beta</title></head><body><p>This is the Beta page.</p><p><a href="/alpha">Previous</a></p></body>
</html>
' does not match PCRE pattern "/Alpha/i".FAILURES!
Tests: 8, Assertions: 23, Failures: 2.复制代码

然而测试失败了。如果你仔细观察我们的新 HTML,你将注意到我们分别有术语 beta 和 alpha 在 /alpha 和 /beta 页面。这意味着我们需要稍微更改我们的测试让它们与误报不匹配。

在每一个 AlphaTest 和 BetaTest 类,更新 testDisplays* 方法去使用 dontSee('<page> page')。通过这种方式,这将仅仅匹配字符串而不是那个术语。

两个测试文件如下所示:

./tests/AlphaTest.php

<?php
class AlphaTest extends TestCase
{public function testDisplaysAlpha(){$this->visit('/alpha')->see('Alpha')->dontSee('Beta page');}public function testClickNextForBeta(){$this->visit('/alpha')->click('Next')->seePageIs('/beta');}
}复制代码

./tests/BetaTest.php

<?php
class BetaTest extends TestCase
{public function testDisplaysBeta(){$this->visit('/beta')->see('Beta')->dontSee('Alpha page');}public function testClickNextForAlpha(){$this->visit('/beta')->click('Previous')->seePageIs('/alpha');}
}复制代码

再一次运行你的测试,所有的测试都应该通过了。我们现在已经测试我们所有的新文件,包括页面中的 Next/Previous 链接。

通过 Semaphore 对 PHPUnit 持续集成

通过 Semaphore设置 持续集成你可以自动执行你的测试。

这样每一次你进行 git push 提交代码的时候都会执行你的测试,并且 Semaphore 预装了所有最新的 PHP 版本。

如果你还没有一个 Semaphore 账户, 先去 注册一个免费的 Semaphore 账户 。接下来需要做的是将它 添加到你的项目,并按照提示逐步去做来执行你的测试:

composer install --prefer-source
phpunit复制代码

关于 PHP 持续集成 的更多信息,请参照 Semaphore 文档。

结语

你应该注意到本教程中的所有测试都有一个共同的主题:它们都非常简单。 这是学习如何使用基本的测试断言和辅助函数,并且尽可能的使用它们的好处之一。编写测试越简单,测试就越容易理解和维护。

掌握了本教程中介绍的 PHPUnit 断言之后,你还可以去 PHPUnit 文档 找到更多内容。 所有的断言都遵循基本的模式,但你会发现,在大多数测试中都会返回基本的断言。

对于 PHPUnit 断言来说,Laravel 的测试辅助函数是极好的补充,这让应用程序的测试变的非常容易。也就是说,重要的是要认识到,对于我们写测试,我们只检查关键信息,而不是整个页面。这使得测试变得简单,并允许页面内容随着应用程序的变化而变化。如果关键信息仍然存在,测试仍然通过,每个人都会满意。

文章转自: https://learnku.com/laravel/t/24559
更多文章:https://learnku.com/laravel/c/translations

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

注释标记的原则_它关系到平台如何标记操纵的媒体。 这是设计师应遵循的12条原则。

注释标记的原则By Emily Saltz, Tommy Shane, Victoria Kwan, Claire Leibowicz, Claire Wardle埃米莉萨尔茨 ( Emily Saltz) &#xff0c; 汤米沙恩 ( Tommy Shane) &#xff0c; 关 颖琳 ( Victoria Kwan) &#xff0c; 克莱尔莱博维奇 ( Claire Leibowicz) &#xff0c; 克莱…

saltapi java_搭建基于Jenkins salt-api的运维工具

1. 安装salt-master和salt-minion安装过程不再赘述&#xff0c;请参考http://docs.saltstack.com/en/latest/topics/installation/index.html2. 安装salt-api&#xff0c;cherrypy用来jenkins与salt通信启用salt-api在salt master的配置文件中添加rest_cherrypy:port: 8010host…

他开发了redux,昨晚字节一面却挂了?

大家好&#xff0c;我是若川&#xff0c;诚邀你进群交流学习。今天分享一次直播的记录。我写过redux源码文章。动手按照文中例子学习&#xff0c;我相信会有所收获。学习源码系列、面试、年度总结、JS基础系列redux的作者是谁&#xff1f;Dan&#xff0c;他的全称叫做Dan Abram…

高通董事长:努力降低智能手机价格

高通董事长&#xff1a;努力降低智能手机价格 高通公司董事长兼CEO保罗雅各布近日表示&#xff0c;2011年高通除了继续与各方合作提供高端及各层次智能手机外&#xff0c;将更加致力于降低智能手机的价格。 手机将成为个人生活中心 作为移动通信芯片领域的霸主&#xff0c;高通…

mysql数据库的新特性_【数据库】MySQL新特性归档介绍

MySQL 8.0.17发布了&#xff0c;看了下release note&#xff0c;发现果真如之前预期的那样&#xff0c;恢复了redo log归档(redo log archiving)功能。之所以说是“恢复”&#xff0c;那是因为在InnoDB非常古老的版本(MySQL 4.0.6之前的版本)才存在&#xff0c;之后就取消了&am…

为什么同事写的代码那么优雅~

大家好&#xff0c;我是若川&#xff0c;诚邀你进群交流学习。今天分享一篇相对轻松的代码简洁之道。学习源码系列、面试、年度总结、JS基础系列内容出自《代码整洁之道》、Alex Kondov[1]的博文tao-of-react[2]和《Clean Code of Javascript》image.png代码整洁有什么用&#…

2021 年最值得了解的 Node.js 工具(下)

大家好&#xff0c;我是若川&#xff0c;诚邀你加群长期交流。今天分享一篇用得上的 node 库。下篇。链接地址&#xff1a;https://github.com/huaize2020/awesome-nodejs。上篇是&#xff1a;2021 年最值得了解的 Node.js 工具❝前言&#xff1a;前端时间分享了这些node开源工…

【阿里内部应用】基于Blink为新商业调控打造实时大数据交互查询服务

基于Blink为新商业调控打造实时大数据交互查询服务 案例与解决方案汇总页&#xff1a;阿里云实时计算产品案例&解决方案汇总从IT到DT、从电商到新商业&#xff0c;阿里巴巴的每个细胞都存在大数据的DNA&#xff0c;如何挖掘大数据的价值成为抢占未来先机的金钥匙&#xff0…

Vite 的好与坏

大家好&#xff0c;我是若川&#xff0c;诚邀你进群交流学习。今天分享一篇关于Vite的文章。学习源码系列、面试、年度总结、JS基础系列。全文 3000 字&#xff0c;欢迎点赞关注转发一、Vite 是什么2020年4月&#xff0c;尤大大发了这么一个推&#xff1a;随后&#xff0c;2021…

Windows phone 7新开发工具发布

春节假期已经接近尾声. 马上第一个工作日就要来临. 春节真的不再是一个简简单单的节日. 有时让人感到欣喜 这意味这一年的忙碌都会因为这个节日的到来而画上一个终止符.面临一个不长也不短的假期.眼下的一年翻过去 新的一年即将到来. 似乎一切都可以重新开始. 有时又令人感到无…

opentaps mysql_opentaps 1.4 联接 mysql 笔记

opentaps 1.4 连接 mysql 笔记一、安装 MySQ 略...二、创建MySQL Database opentaps ERP CRM1.mysql -u root -h 127.0.0.1 -p 2.mysql>create database opentaps default CHARACTER SET utf8 COLLATE utf8_general_ci;3.mysql>create user opentaps;4.mysql>grant …

React 核心开发者 Dan Abramov 访谈实录

大家好&#xff0c;我是若川。面试、学习源码系列、年度总结、JS基础系列译者注&#xff1a;本译文是在「在线对话 React.js 核心开发者」一个半小时直播的基础上进行的原文翻译&#xff0c;包括了直播中的所有问答内容&#xff0c;尽可能保留了 Dan 回答的中心语义&#xff0c…

python ev3图形化编程软件下载_mPython(图形化编程软件)

mPython是盛思技术团队在BBC官方原版PythonEditor基础上、拓展开发的应用软件。可以进行可视化代码编程&#xff0c;有hex、python、blockly三种代码读写等功能。功能介绍1、不依赖网络&#xff0c;可离线安装使用2、支持hex、python、blockly三种代码的读写3、blockly模式下支…

python如何安装panda数据库_在Pycharm中安装Pandas库方法(简单易懂)

开发环境的搭建是一件入门比较头疼的事情&#xff0c;在上期的文稿基础上&#xff0c;增加一项Anaconda的安装介绍。Anaconda是Python的一个发行版本&#xff0c;安装好了Anaconda就相当于安装好了Python&#xff0c;并且里面还集成了很多Python科学计算的第三方库。比如我们需…

译文 | Vue 在哪些方面做的比 React 更好?

大家好&#xff0c;我是若川。在过去的五年中&#xff0c;我一直是一名 React 工程师。我爱React。我喜欢开发 React 应用程序。我认为它是目前最好的UI框架之一。但是&#xff0c;在这个领域有一些竞争对手。其中最大的是 Vue.js 。我以前玩过一些 Vue.js&#xff0c;但我认为…

web mp4第一帧_Web成帧器就在这里!

web mp4第一帧The Framer Team is pulling up it’s pants. I sniffed something cooking when they announced a public beta for Framer for web… FRAMER FOR WEB? Yes, I don’t know how they did it, but their powerful set of tools, plugins and animation controls …

Lucene学习总结之三:Lucene的索引文件格式(2)

2019独角兽企业重金招聘Python工程师标准>>> 四、具体格式 上面曾经交代过&#xff0c;Lucene保存了从Index到Segment到Document到Field一直到Term的正向信息&#xff0c;也包括了从Term到Document映射的反向信息&#xff0c;还有其他一些Lucene特有的信息。下面对这…

JavaScript 数组 API 全解析

在编程世界中&#xff0c;数组是指元素的集合。数组将数据作为元素进行存储&#xff0c;并在需要时将其取出。在支持数组的编程语言中广泛地采用了这个数据结构。这个手册会介绍 JavaScript 数组的所有知识。你将会学到复杂数据处理、解构、常用数组方法等内容。我为什么写这篇…

美学设计评价_死亡的孩子无法使用的设计美学

美学设计评价In the popular anime series, Soul Eater, Death the Kid is a Shinigami (Japanese death god) who vanquishes evil with his dual pistols, Liz and Patty. Although he’s strikingly powerful, his battles are often hindered by his obsessive-compulsive …

【送书】2021年哪些好书值得读(小姐姐配音)

大家好&#xff0c;我是若川。记得点上面的小姐姐再次录制的配音。为感谢大家一直以来的支持和肯定。不知道是今年第几次送书了。昨天送书的音频广受好评&#xff0c;没参与的可以参与。今天联合华章图书再送文中任选一本 * 3 包邮送&#xff0c;详细规则看文末。Web开发01《斯…