drupal模块

In this article we are going to look at automated testing in Drupal 8. More specifically, we are going to write a few integration tests for some of the business logic we wrote in the previous Sitepoint articles on Drupal 8 module development. You can find the latest version of that code in this repository along with the tests we write today.

在本文中,我们将研究Drupal 8中的自动化测试。更具体地说,我们将为先前在Sitepoint上有关Drupal 8模块开发的文章中编写的一些业务逻辑编写一些集成测试。 您可以在此存储库中找到该代码的最新版本,以及我们今天编写的测试。

But before doing that, we will talk a bit about what kinds of tests we can write in Drupal 8 and how they actually work.

但是在此之前,我们将先讨论一下我们可以在Drupal 8中编写哪些测试以及它们如何实际工作。

最简单(测试) (Simpletest (Testing))

Simpletest is the Drupal specific testing framework. For Drupal 6 it was a contributed module but since Drupal 7 it has been part of the core package. Simpletest is now an integral part of Drupal core development, allowing for safe API modifications due to an extensive codebase test coverage.

Simpletest是Drupal特定的测试框架。 对于Drupal 6,它是一个贡献模块,但是自Drupal 7起,它已成为核心软件包的一部分。 现在,Simpletest已成为Drupal核心开发不可或缺的一部分,由于广泛的代码库测试涵盖范围,因此可以进行安全的API修改。

Right off the bat I will mention the authoritative documentation page for Drupal testing with Simpletest. There you can find a hub of information related to how Simpletest works, how you can write tests for it, what API methods you can use, etc.

马上,我将提到使用Simpletest进行Drupal测试的权威文档页面 。 在这里,您可以找到与Simpletest的工作方式,如何编写测试,可以使用的API方法等相关的信息中心。

By default, the Simpletest module that comes with Drupal core is not enabled so we will have to do that ourselves if we want to run tests. It can be found on the Extend page named as Testing.

默认情况下,Drupal核心随附的Simpletest模块未启用,因此如果要运行测试,我们必须自己做。 可以在名为Testing的扩展页面上找到它。

Once that is done, we can head to admin/config/development/testing and see all the tests currently available for the site. These include both core and contrib module tests. At the very bottom, there is also the Clean environment button that we can use if any of our tests quit unexpectedly and there are some remaining test tables in your database.

完成后,我们可以进行admin/config/development/testing并查看该站点当前可用的所有测试。 这些包括核心和贡献模块测试。 在最底部,如果有任何测试意外退出并且您的数据库中还有一些剩余测试表,我们还可以使用“ Clean environment按钮。

Simpletest如何工作? (How does Simpletest work?)

When we run a test written for Simpletest, the latter uses the existing codebase and instructions found in the test to create a separate Drupal environment in which the test can run. This means adding additional tables to the database (prefixed by simpletest_) and test data that are used to replicate the site instance.

当我们运行为Simpletest编写的测试时,后者会使用现有的代码库和在测试中找到的说明来创建一个单独的Drupal环境,在该环境中可以运行该测试。 这意味着向数据库中添加其他表(以simpletest_为前缀),并测试用于复制站点实例的数据。

Depending on the type of test we are running and what it contains, the nature of this replication can differ. In other words, the environment can have different data and core functionality depending on the test itself.

根据我们正在运行的测试类型及其包含的内容,此复制的性质可能有所不同。 换句话说,根据测试本身,环境可以具有不同的数据和核心功能。

Drupal 8中有哪些测试? (What kinds of tests are there in Drupal 8?)

There are two main types of tests that we can write for Drupal 8: unit tests using PHPUnit (which is in core now) and functional tests (using Simpletest). However, the latter can also be split into two different kinds: web tests (which require web output) and kernel tests (which do not require web output). In this article we will practically cover only web tests because most of the functionality we wrote in the previous articles is manifested through output so that’s how we need to test it as well.

我们可以为Drupal 8编写两种主要的测试类型:使用PHPUnit的单元测试(现在是核心)和功能测试(使用Simpletest)。 但是,后者也可以分为两种: Web测试 (需要Web输出)和内核测试 (不需要Web输出)。 在本文中,我们实际上将仅涵盖Web测试,因为我们在前几篇文章中编写的大多数功能都是通过输出来体现的,因此我们也需要对其进行测试。

Writing any type of test starts by implementing a specific class and placing it inside the src/Tests folder of the module it tests. I also encourage you to read this documentation page that contains some more information on this topic as I do not want to duplicate it here.

要编写任何类型的测试,首先要实现一个特定的类,然后将其放在要src/Tests的模块的src/Tests文件夹中。 我也鼓励您阅读此文档页面 ,其中包含有关此主题的更多信息,因为我不想在此处重复。

我们的测试 (Our tests)

As I mentioned, in this article we will focus on providing test coverage for some of the business logic we created in the series on Drupal 8 module development. Although there is nothing complicated happening there, the demo module we built offers a good example for starting out our testing process as well. So let’s get started by first determining what we will test.

就像我提到的那样,在本文中,我们将重点介绍对我们在Drupal 8模块开发系列中创建的一些业务逻辑的测试覆盖范围。 尽管没有什么复杂的事情发生,但是我们构建的demo模块还是一个很好的例子,也可以用来启动我们的测试过程。 因此,让我们首先确定要测试的内容。

By looking at the demo module, we can delineate the following aspects we can test:

通过查看演示模块 ,我们可以描述可以测试的以下方面:

  • We have a route that displays a page with a specific message loaded from a service.

    我们有一条路线 显示一个页面,其中包含从服务加载的特定消息。

  • We have a route that displays a form and which has some configuration.

    我们有一条显示表单并具有一些配置的路由 。

  • We have a custom block plugin we can configure and add to a page.

    我们有一个自定义块插件,我们可以配置并添加到页面。

That’s pretty much it. The custom menu link we defined inside the demo.links.menu.yml could also be tested but that should already work out of the box so I prefer not to.

就是这样。 我们在demo.links.menu.yml定义的自定义菜单链接也可以进行测试,但是应该已经可以使用,所以我不希望这样做。

For the sake of brevity and the fact that we don’t have too much we need to test, I will include all of our testing methods into one single class. However, you should probably group yours into multiple classes depending on what they are actually responsible for.

为了简洁起见,以及我们不需要进行过多测试的事实,我将所有测试方法都包含在一个类中。 但是,您可能应该根据自己的实际职责将其分为多个类。

Inside a file called DemoTest.php located in the src/Tests/ folder, we can start by adding the following:

src/Tests/文件夹中名为DemoTest.php文件中,我们可以从添加以下内容开始:

<?php
namespace Drupal\demo\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the Drupal 8 demo module functionality
*
* @group demo
*/
class DemoTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('demo', 'node', 'block');
/**
* A simple user with 'access content' permission
*/
private $user;
/**
* Perform any initial set up tasks that run before every test method
*/
public function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(array('access content'));
}
}

Here we have a simple test class which for every test it runs, will enable the modules in the $modules property and create a new user stored inside the $user property (by virtue of running the setUp() method).

在这里,我们有一个简单的测试类,它针对每次运行的测试都将启用$modules属性中的$modules并创建一个存储在$user属性中的新用户(通过运行setUp()方法)。

For our purposes, we need to enable the demo module because that is what we are testing, the block module because we have a custom block plugin we need to test and the node module because our logic uses the access content permission defined by this module. Additionally, the user is created just so we can make sure this permission is respected.

出于我们的目的,我们需要启用demo模块,因为这是我们要测试的模块; block模块,因为我们有需要测试的自定义块插件; node模块,因为我们的逻辑使用了此模块定义的access content权限。 此外,创建用户只是为了确保可以确保此权限。

For the three bullet points we identified above, we will now create three test methods. Keep in mind that each needs to start with the prefix test in order for Simpletest to run them automatically.

对于上面确定的三个要点,我们现在将创建三种测试方法。 请记住,为了使Simpletest自动运行它们,每个都需要以前缀test开始。

测试页面 (Testing the page)

We can start by testing the custom page callback:

我们可以从测试自定义页面回调开始:

/**
* Tests that the 'demo/' path returns the right content
*/
public function testCustomPageExists() {
$this->drupalLogin($this->user);
$this->drupalGet('demo');
$this->assertResponse(200);
$demo_service = \Drupal::service('demo.demo_service');
$this->assertText(sprintf('Hello %s!', $demo_service->getDemoValue()), 'Correct message is shown.');
}

And here is the code that does it.

这是执行此操作的代码。

First, we log in with the user we created in the setUp() method and then navigate to the demo path. Simpletest handles this navigation using its own internal browser. Next, we assert that the response of the last accessed page is 200. This validates that the page exists. However, this is not enough because we need to make sure the text rendered on the page is the one loaded from our service.

首先,我们使用在setUp()方法中创建的用户登录,然后导航到demo路径。 Simpletest使用其自己的内部浏览器来处理此导航。 接下来,我们断言上次访问的页面的响应为200。这验证了该页面的存在。 但是,这还不够,因为我们需要确保页面上呈现的文本是从服务中加载的文本。

For this, we statically access the \Drupal class and load our service. Then we assert that the page outputs the hello message composed of the hardcoded string and the return value of the service’s getDemoValue() method. It’s probably a good idea to write a unit test for whatever logic happens inside the service but for our case this would be quite redundant.

为此,我们静态访问\Drupal类并加载我们的服务。 然后,我们断言页面输出的hello消息由硬编码的字符串和服务的getDemoValue()方法的返回值组成。 为服务内部发生的任何逻辑编写单元测试可能是一个好主意,但是对于我们而言,这将是非常多余的。

And that’s it with the page related logic. We can go to the testing page on our site, find the newly created DemoTest and run it. If all is well, we should have all green and no fails.

就是页面相关逻辑。 我们可以转到我们网站上的测试页面,找到新创建的DemoTest并运行它。 如果一切顺利,我们应该拥有全部绿色,没有失败。

测试表格 (Testing the form)

For the form we have another method, albeit more meaty, that tests all the necessary logic:

对于表单,我们还有另一种方法,尽管更加实用,它可以测试所有必要的逻辑:

/**
* Tests the custom form
*/
public function testCustomFormWorks() {
$this->drupalLogin($this->user);
$this->drupalGet('demo/form');
$this->assertResponse(200);
$config = $this->config('demo.settings');
$this->assertFieldByName('email', $config->get('demo.email_address'), 'The field was found with the correct value.');
$this->drupalPostForm(NULL, array(
'email' => 'test@email.com'
), t('Save configuration'));
$this->assertText('The configuration options have been saved.', 'The form was saved correctly.');
$this->drupalGet('demo/form');
$this->assertResponse(200);
$this->assertFieldByName('email', 'test@email.com', 'The field was found with the correct value.');
$this->drupalPostForm('demo/form', array(
'email' => 'test@email.be'
), t('Save configuration'));
$this->assertText('This is not a .com email address.', 'The form validation correctly failed.');
$this->drupalGet('demo/form');
$this->assertResponse(200);
$this->assertNoFieldByName('email', 'test@email.be', 'The field was found with the correct value.');
}

The first step is like before. We go to the form page and assert a successful response. Next, we want to test that the email form element exists and that its default value is the value found inside the default module configuration. For this we use the assertFieldByName() assertion.

第一步就像以前一样。 我们进入表单页面并声明成功的响应。 接下来,我们要测试email表单元素是否存在,并且其默认值是在默认模块配置中找到的值。 为此,我们使用assertFieldByName()断言。

Another aspect we need to test is that saving the form with a correct email address does what it is supposed to: save the email to configuration. So we use the drupalPostForm() method on the parent class to submit the form with a correct email and assert that a successful status message is printed on the page as a result. This proves that the form saved successfully but not necessarily that the new email was saved. So we redo the step we did earlier but this time assert that the default value of the email field is the new email address.

我们需要测试的另一方面是,使用正确的电子邮件地址保存表单可以达到预期的效果:将电子邮件保存到配置中。 因此,我们在父类上使用drupalPostForm()方法提交带有正确电子邮件的表单,并断言结果是在页面上打印了成功的状态消息。 这证明表单已成功保存,但未必已保存新电子邮件。 因此,我们重做我们之前做的步骤,但是这次声明电子邮件字段的默认值为新的电子邮件地址。

Finally, we need to also test that the form doesn’t submit with an incorrect email address. We do so again in two steps: test a form validation failure when submitting the form and that loading the form again will not have the incorrect email as the default value of the email field.

最后,我们还需要测试表单是否使用错误的电子邮件地址提交。 我们分两个步骤再次进行此操作:提交表单时测试表单验证失败,并且再次加载表单不会将不正确的电子邮件作为电子邮件字段的默认值。

测试块 (Testing the block)

/**
* Tests the functionality of the Demo block
*/
public function testDemoBlock() {
$user = $this->drupalCreateUser(array('access content', 'administer blocks'));
$this->drupalLogin($user);
$block = array();
$block['id'] = 'demo_block';
$block['settings[label]'] = $this->randomMachineName(8);
$block['theme'] = $this->config('system.theme')->get('default');
$block['region'] = 'header';
$edit = array(
'settings[label]' => $block['settings[label]'],
'id' => $block['id'],
'region' => $block['region']
);
$this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], $edit, t('Save block'));
$this->assertText(t('The block configuration has been saved.'), 'Demo block created.');
$this->drupalGet('');
$this->assertText('Hello to no one', 'Default text is printed by the block.');
$edit = array('settings[demo_block_settings]' => 'Test name');
$this->drupalPostForm('admin/structure/block/manage/' . $block['id'], $edit, t('Save block'));
$this->assertText(t('The block configuration has been saved.'), 'Demo block saved.');
$this->drupalGet('');
$this->assertText('Hello Test name!', 'Configured text is printed by the block.');
}

For this test we need another user that also has the permission to administer blocks. Then we create a new instance of our custom demo_block with no value inside the Who field and assert that a successful confirmation message is printed as a result. Next, we navigate to the front page and assert that our block shows up and displays the correct text: Hello to no one.

对于此测试,我们需要另一个也具有管理块权限的用户。 然后,我们在Who字段中创建一个没有值的自定义demo_block的新实例,并断言结果将显示成功的确认消息。 接下来,我们导航到首页,并断言我们的代码块会显示并显示正确的文本: Hello to no one

Lastly, we edit the block and specify a Test name inside the Who field and assert that saving the block configuration resulted in the presence of a successful confirmation message. And we close off by navigating back to the home page to assert that the block renders the correct text.

最后,我们编辑块并在Who字段中指定Test name ,并断言保存块配置会导致出现成功的确认消息。 最后,我们导航回到主页,断言该块呈现了正确的文本。

结论 (Conclusion)

In this article, we’ve seen how simple it is to write some basic integration tests for our Drupal 8 business logic. It involves creating one or multiple class files which simply make use of a large collection of API methods and assertions to test the correct behavior of our code. I strongly recommend you give this a try and start testing your custom code early as possible in order to make it more stable and less prone to being broken later on when changes are made.

在本文中,我们已经看到为我们的Drupal 8业务逻辑编写一些基本的集成测试是多么简单。 它涉及创建一个或多个类文件,这些文件仅利用大量API方法和断言来测试我们代码的正确行为。 我强烈建议您尝试一下,并尽早开始测试您的自定义代码,以使其更稳定并且在以后进行更改时不易被破坏。

Additionally, don’t let yourself get discouraged by the slow process of writing tests. This is mostly only in the beginning until you are used to the APIs and you become as fluent as you are with the actual logic you are testing. I feel it’s important to also mention that this article presented a very high level overview of the testing ecosystem in Drupal 8 as well as kept the tests quite simple. I recommend a more in depth look into the topic going forward.

此外,不要因为编写测试的过程缓慢而气yourself。 在您习惯使用API​​之前,这几乎只是一开始,并且变得与您正在测试的实际逻辑一样流利。 我感到很重要的一点是,本文还对Drupal 8中的测试生态系统进行了高度概括,并保持了测试的简单性。 我建议更深入地研究该主题。

翻译自: https://www.sitepoint.com/automated-testing-drupal-8-modules/

drupal模块

drupal模块_自动测试Drupal 8模块相关推荐

  1. 乐玩自动化测试模块_五大测试框架介绍,附带全套黑马自动化测试视频教程(完结)...

    这个框架需要开发数据表和关键字,这些数据表和关键字独立于执行它们的测试自动化工具,并可以用来"驱动"待测应用程序和数据的测试脚本代码,关键宇驱动测试看上去与手工测试用例很类似. 概述 在自动 ...

  2. autosar中com模块_详细介绍AUTOSAR各个模块作用PART1(OS,SYS)

    这片文章中我们详细讲解下每个模块的功能,上图是vector的autosar方案,每个模块的详细介绍后续会有单独文章进行讲解,请关注.以下是各个模块的简介 1.VHSM hardware Securit ...

  3. import pymysql 没有模块_小白详细的 python 模块的运用

    小白详细的 python 模块的运用 什么是模块 用书里的话说:模块是最高级别的程序组织单元.这句话的意思是,模块什么都能封装,就像这样: 在模块中,我们不但可以直接存放变量,还能存放函数,还能存放类 ...

  4. 万兆单模模块_华为万兆单模模块 OEM光模块 全面兼容OSX010000

    中性光纤模,适用于国内外多种网络设备:华三.华为.锐捷.中兴.迪普等多种网络交换机等设备 光模块 FE-SFP光模块 SFP-FE-LH40-SM1310       光模块-eSFP-FE-单模模块 ...

  5. 无源波分和彩光模块_易飞扬彩光模块百科

    彩光模块即彩色光模块,是光复用传输链路中的光电转换器,它也被叫做WDM波分光模块.WDM光模块属于无源模块,本身不发射激光,一般使用光平面波导(PLC)技术,只是将一束光分成数束光.而普通光模块属于光 ...

  6. asdm如何管理ips模块_自动驾驶深受高精度定位困扰,ST如何应对挑战?

    据估计,在今天的汽车行业中80%的创新都是通过电子设备直接或间接实现的.随着每款新车的各种功能不断升级,每辆车中的半导体器件都在不断增加. 在2019慕尼黑上海电子展上,汽车电子行业领先企业意法半导体 ...

  7. 光模块自动测试系统软件,光模块自动化测试系统

    目前业界最先进的光模块测试平台 OPM光模块自动化测试系统 一支持32位或者64位操作系统,包括XP,WINDOWS7,WINDOWS10.二人工测试需要测试人员具有很高的专业技术要求,测试效率低,容 ...

  8. 易语言mysql连接模块_易语言mysql链接模块libmySQL6.1模块源码

    .版本 2 .支持库 spec .程序集 libmySQL .子程序 _启动子程序, 整数型, , 请在本子程序中放置易模块初始化代码 _临时子程序 ()  ' 在初始化代码执行完毕后调用测试代码 返 ...

  9. python shelve模块_说说 Python 的 shelve 模块

    利用 Python 的 shelve 模块, 可以将程序中需要保存的数据,以二进制放入 shelf 文件中.另一个程序就可以读取 shelf 文件,用于业务逻辑.也就是说 shelve 模块可以实现数 ...

  10. python中怎样使用re模块_[转]Python中RE模块的应用

    Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式.Python 1.5之前版本则是通过 regex 模块提供 Emecs 风格的模式.Emacs 风格模式可读性稍差 ...

最新文章

  1. sqlalchemy mysql教程_python使用SQLAlchemy操作MySQL
  2. matlab 凹盘,刹车盘凹槽是怎么形成的
  3. jzoj2940-生成输入数据【最小生成树,并查集】
  4. php组成,php接口有几部分组成?
  5. unity3d由多个部分组成一个角色
  6. 关于redis的持久化
  7. python列表的加法_Python列表加法理解
  8. 前端菜鸟是这样入门学习的,点进来!
  9. 我的图书《深入浅出线性代数》
  10. 如何限制计算机游戏,如何禁止玩电脑游戏、屏蔽网络游戏方法
  11. 使用Requests爬取网页图片并保存
  12. ykhmi是什么触摸屏软件_YKHMI 中达优控7寸一体机兼容台达ES2
  13. 黄山学院计算机专业考研情况,为什么考入北大的研究生偏偏来自黄山学院这样的学校?...
  14. K. 冒险公社 (线性DP)
  15. Maya菜单中英文对照表(一)
  16. 专题·置换【including 置换,置换快速幂,洛谷·[HNOI2001]洗牌机
  17. easyexcel实现代码生成xlsx文件并保存到云端
  18. GB2312-80 所有汉字排序,拼音
  19. KANO模型以及产品经理的素质模型
  20. antd Upload 文件上传

热门文章

  1. js+css实现瀑布流
  2. 锐捷服务器无线认证配置,锐捷AC CMCC-WEB认证配置详解
  3. 车金融|金融产品规则引擎的前世今生(中篇)
  4. win7任务管理器没有的找到方法
  5. 自动驾驶的“第三眼美女“什么时候才能出现?
  6. 道路中心线提取、河道中心线的提取(ArcScan)
  7. Web Dynpro for ABAP ( 四 ) BPM系统的连接
  8. 8421 5421 2421 余3码
  9. 某大厂程序员吐槽外包员工是大爷
  10. Vue传递参数不在URL路径上 显示参数的完整方法