Drupal SimpleTest是一个模块,可让您对自己的模块进行单元测试或对第三方模块制作的任何补丁进行单元测试。该模块将集成到Drupal 7中,但是对于Drupal 6,您必须做几次尝试才能开始测试。本文是对Drupal SimpleTest的快速介绍,以后还会有更多文章作为后续内容。
第一步是像下载其他模块一样下载并安装SimpleTest模块。如果您知道如何使用Drush可以执行此操作。
运行Drupal之后,您需要给Drupal的核心打补丁才能运行任何测试。我不需要指出给Drupal核心打补丁是有风险的,在生产方面也不应该这么做。事实上,你想要安装SimpleTest就意味着你要进行测试,在这种情况下,你要在开发服务器上完成所有这些,对吗?
无论如何,有几种方法可以将补丁(可以在 SimpleTest 模块目录中找到)应用到 Drupal 安装中。CVS 方法(如 Simpletestinstall.txtfile 中所述)可能是最快的。
patch -p0 < path/to/simpletest/D6-core-simpletest.patch
但是,这种方法并不总是在所有系统上都可用。在这种情况下,我使用Netbeans IDE来应用补丁。为此,您首先需要将Drupal安装作为项目加载。完成此操作后,右键单击源代码,然后单击“工具”>“应用差异修补程序...”。
Drupal 6 SimpleTest Apply补丁1
然后导航到您的SimpleTest目录,然后选择文件D6-core-simpletest.patch。
Drupal SimpleTest选择补丁文件
应用补丁后,您可以选择查看差异报告中应用的更改。这就是它的样子。
Drupal SimpleTest Netbeans差异报告
从这一点开始,就使用SimpleTest而言,Drupal 6和Drupal 7(除了管理界面)之间没有区别。实际上,SimpleTest已在Drupal 7中被广泛使用,因此与之一起打包。
您可以像安装其他任何Drupal模块一样安装SimpleTest模块,甚至可以在安装补丁之前进行安装。该补丁实际上仅是运行测试所需要的。要找到测试管理员页面,请转至站点构建>测试或URL / admin / build / testing,此页面将向您显示当前安装中可用的当前测试。默认情况下,您将看到SimpleTest测试,但是安装的模块越多,您将看到的测试越多。下面的屏幕快照显示了SimpleTest管理屏幕,其中安装了几个模块。
SimpleTest管理页面
通过单击测试旁边的复选框,您可以一起运行一组测试,但也可以单击组名,这将生成一个单独测试的列表,您可以一次运行一个测试。当您运行任何测试时,您将看到一个带有进度条的页面,该进度条显示正在运行的测试以及测试完成时,您将看到一个关于哪些测试通过或失败的报告。
SimpleTest的工作原理
在开始使用SimpleTest编写测试之前,了解系统是如何工作的是很重要的。当通过SimpleTest运行测试时,它使用临时表名前缀安装新版本的Drupal,运行测试,然后删除创建的表。文件的情况稍有不同,因为它们会像平常一样被复制或移动,所以测试运行后,您需要注意清理它们。
由于每次测试运行时都会执行新的Drupal安装,因此您需要确保将代码执行超时设置为非常高,否则测试运行可能会失败。要意识到的最重要的一点是,当SimpleTest安装Drupal时,它是一个非常基本的安装,没有安装任何模块(当前正在测试的模块除外)或任何其他定义的模块。这意味着,如果您想测试您的模块以及CCK或Views模块,您必须先启用它们,然后才能在测试中使用它们。同样的情况也适用于任何变量、用户、节点或任何您可能希望在新安装中创建的其他内容。
有些人可能认为这是在Drupal中创建单元测试的一个弱点,但它确实让您思考代码在应用程序中所做的一切,它将如何与用户、节点、模块和主题交互,这也许就是单元测试的全部内容?
如果您的测试导致代码在测试运行的中途掉了下来,那么您将需要清理创建的临时表。SimpleTest管理区中有一个按钮,标记为“Clean Up”,允许您执行此操作。如果代码超时,测试可能会中途失败,但如果代码中有任何语法错误,测试也会失败。
在你开始之前
要为自己的模块创建单元测试,您需要在模块目录中创建扩展名为“ .test”的文件。对于简单的模块,您只需在模块的根目录中创建一个文件。对于具有多个测试文件和相关资源(例如,测试中使用的文件)的更复杂的模块,可以将所有内容包括在名为test的目录中,SimpleTest也会寻找该目录。
SimpleTest以面向对象的方式使用,因此要运行测试,您可以扩展两个类之一并添加自己的测试功能。这些类是DrupalWebTestCase和DrupalUnitTestCase,根据您要测试哪种类型,使用哪种类。DrupalUnitTestCase类仅应用于测试不需要数据库或文件级别访问的内容。这些就是字符串操作或计算之类的东西。在测试Drupal环境内的其他所有内容时,应使用DrupalWebTestCase类。
为了使SimpleTest注册您的测试并将其添加到SimpleTest管理页面,您需要添加一个称为getInfo()扩展类的方法。下面定义了一个非常简单的测试类,它不会运行任何测试。该getInfo()方法返回一个具有元素名称,描述和组的关联数组。名称是类的名称,描述将显示该类中要测试的内容,并且SimpleTest使用该组将测试分组在一起。
class MyModuleTest extends DrupalWebTestCase { /** * Create an array of options for the simpletest module. * * @return array The array of options */ public function getInfo() { return array( 'name' => t('MyModule Example Test Class'), 'description' => t('A description of what the class tests.'), 'group' => t('MyModule'), ); } }
在模块目录中创建此文件后,您将需要清除缓存以使其显示在SimpleTest管理区域中。如果要测试模块的不同方面,则可以创建多个这些文件之一。将测试根据功能或文件划分为多个部分也是一个好主意。在我们开始编写测试之前,必须引入两个重要的方法,分别是setUp()和tearDown()。
该setUp()功能用于使默认的Drupal安装与您要测试的安装保持一致。这包括诸如安装模块,创建变量,添加用户甚至登录用户之类的事情。该setUp()方法是您尝试进行任何测试之前最重要的步骤。
该tearDown()函数用于清除您在测试中所做的任何事情。并不是每个测试类都需要这样做,因为SimpleTest会自己执行大部分清理工作,但是有时您希望将所有更改或移动的文件恢复为原始状态,因此在这种情况下很有用。
对于运行的每个测试,SimpleTest将运行该setUp()方法,然后运行该测试,然后运行该tearDown()方法。
以下是上一类,其中包含getInfo()方法以及setUp()和tearDown()方法。
class MyModuleTest extends DrupalWebTestCase { /** * Create an array of options for the simpletest module. * * @return array The array of options */ public function getInfo() { return array( 'name' => t('MyModule Example Test Class'), 'description' => t('A description of what the class tests.'), 'group' => t('MyModule'), ); } /** * SimpleTest core method: code run before each and every test method. * * Optional. You only need this if you have setup tasks. */ public function setUp() { // 始终从父类调用setUp()方法。 parent::setUp(); } /** * SimpleTest core method: code run after each and every test method. * * Optional. You only need this if you have setup tasks. */ public function tearDown() { // 始终从父类中调用tearDown()方法。 parent::tearDown(); } }
要使用该setUp()方法启用模块,只需一次将它们作为字符串参数传递一次即可。例如,要启用“内容”,“视图”和“上下文”模块(随机选择三个),可以执行以下操作。
parent::setUp('content', 'views', 'context');
请注意,您不需要在setUp()方法中包括自己的模块,SimpleTest将为您完成此操作。
做你自己的测试
要运行自己的测试,您所要做的就是创建带有前缀“ test”的方法。SimpleTest将自动选择这些方法,并将它们添加到将要运行的测试列表中。一旦确定了要测试的内容,就可以使用SimpleTest的内置测试功能来检查输出。SimpleTest带有许多测试功能,这些功能使您可以断言像对单元进行测试时通常所做的那样。下面的代码是一种测试方法的简单示例,该方法检查模块中函数的返回值。
public function testCheckText() { $expected_text = 'expected text'; $text = my_module_text_function('input text'); $this->assertTrue($text == $expected_text, t('Checking text alteration function.')); }
这是SimpleTest中可用的许多不同断言方法之一的示例,并且由于我们正在扩展包含这些方法的SimpleTest类,因此需要使用$this来调用它们。使用assertTrue()此处的一种替代方法是使用assertEqual(),其工作方式大致相同,但是这里的前两个参数是您要比较的两个变量。以下是与上述相同的测试,但是使用assertEqual()代替编写。
public function testCheckText() { $expected_text = 'expected text'; $text = my_module_text_function('input text'); $this->assertEqual($text, $expected_text, t('Checking text alteration function.')); }
有关可用的不同断言的完整列表,请查看SimpleTest断言参考页面。
辅助功能
到目前为止,我只研究了最基本的逻辑测试,但是在Drupal站点中有很多要测试的东西,SimpleTest附带了一堆有用的方法,使您可以执行某些操作或以不同的方式将数据发送到Drupal。方法。
两种最有用的帮助器方法是drupalPost()和drupalGet(),分别执行发布(表单提交)和获取(Web浏览)请求。
drupalPost()例如,在提交某种形式的表单时,该方法用于将发布数据发送到Drupal。在Drupal站点中提交表单的最常见示例是创建节点。通常在Drupal中,您将通过创建一个对象,然后将其传递给node_save()函数来创建节点。但是,SimpleTest允许您通过以与通常相同的方式提交添加节点表单来创建节点。关于此方法的好处是,与使用另一个名为的SimpleTest helper方法一样,您还将测试登录用户的特权drupalLogin()。这是drupalPost()创建节点的方法的示例。的返回值drupalPost()是从发布请求发送回的输出,然后可以测试此输出。
$edit = array(); $edit['title'] = 'Node title'; $edit['body'] = 'Node body'; $output = $this->drupalPost('node/add/page', $edit, t('Save'));
SimpleTest还为我们提供了一种使用该drupalCreateNode()方法执行此操作的简便方法,该方法的工作方式非常相似。
$node_array = array( 'type' => 'page', 'title' => 'Node title', 'body' => 'Node body', ); $node = $this->drupalCreateNode($node_array);
该drupalGet()方法等效于该drupalPost()方法。这样,您就可以在创建节点,添加用户以及模块将要执行的其他操作时检查操作的结果。以下代码片段将获取页面的HTML内容并将其返回,以供您测试预期的字符串。
$output = $this->drupalGet('node/' . $node->nid));
测试get或post调用的返回输出是确保操作具有正确效果的一种方法。但是,无论何时在SimpleTest中执行操作,它都会存储在内部浏览器中,然后可以用与检查返回的输出中的预期结果相同的方式对其进行测试。例如,假设我们使用drupalPost()方法创建了一个节点,然后可以使用assertRaw()查看是否保存了要保存的内容来测试页面的输出。
public function testCreateNode() { $edit = array(); $edit['title'] = 'Node title'; $edit['body'] = 'Node body'; $this->drupalPost('node/add/page', $edit, t('Save')); $this->assertRaw('Node title', t('Node output found.')); }
起初这可能会造成混淆,因为它看起来似乎并没有assertRaw()在做任何事情,但是它只是查看当前页面,因此不需要传递输出变量。
调试
在SimpleTest中调试不是那么简单,如果您打印出任何内容,它将被忽略并且您将永远看不到它。SimpleTest带有调试模式,您可以在运行测试时激活它以打印或保存信息。转到位于/ admin / build / testing / settings的SimpleTest管理页面,并检查标记为“运行测试时提供详细信息”的设置。启用此功能后,每次调用drupalGet()或drupalPost()将其内容捕获为HTML文件。您还可以通过调用verbose()方法并将一些调试输出传递给该方法,将输出消息发送到测试结果页面。
$this->verbose('Array contents: ' . var_export($array, true));
Drupal SimpleTest的功能比我在这里概述的要多得多,但这应该可以帮助您开始在Drupal中进行单元测试。我希望以后再写一些有关SimpleTest的文章,因此,如果有兴趣,请确保您订阅了feed。