HTML输出的单元测试?

时间:2010-08-07 05:17:58

标签: php html unit-testing templates

这可能是一个愚蠢的问题,但你是否对PHP函数/脚本的HTML输出进行了单元测试?

我尝试将我的HTML和我的PHP分开 - 即HTML包含占位符,以及某些重复元素的功能(表格数据/任何类型的循环输出) - 但我不确定如何验证这一点。

是否有标准的方法可以解决这些问题,或者主要是对创建插入的内容的函数使用常规单元测试,然后确保它在浏览器中看起来正确/ W3C Validator?

感谢。

编辑:我想这是一个必然结果:这些单元测试是否值得拥有?如果你保持你的内容和结构正确分开,那么你真的只会在非常有限的场景中测试一些包含(无论如何)。是否真的值得半手工制作整页以便将文件与之比较?

10 个答案:

答案 0 :(得分:9)

根据我测试HTML的经验,我现在遵循以下三个基本规则:

<强> 1。不要针对正确的模板测试HTML输出。 您将经常修改输出的HTML,并且最终会浪费时间维护测试。

<强> 2。检查生成的HTML中是否存在重要数据。 如果您正在生成HTML(与您一次编写的静态HTML相反),请测试生成的HTML以获取重要数据。例如:如果您正在基于二维数组生成表,请检查数组中的值是否在生成的HTML中的某处找到。不要费心去验证完整的输出,因为这会违反#1。

第3。验证输出是否是正确的HTML。 验证所有输出是否正确HTML以避免愚蠢的错误,例如缺少结束标记。我为此编写了一个库,可以完全免费使用。

此PHP库将允许您验证字符串是否有效HTML5。该库使用Validator.nu。与PHPUnit或任何其他测试框架兼容。

Download and documentation here.

易于使用,例如:

$validator=new HTML5Validate();

// Validate (returns TRUE or FALSE)
$result=$validator->Assert('<p>Hello World</p>'); 

// Get explanation of what's wrong (if validation failed)
print $validator->message; 

答案 1 :(得分:5)

测试HTML输出将被视为覆盖测试。最初,当我开始使用PHP时,我正在创建这些测试,但随着时间的推移,我发现这些测试并没有真正有用。

如果我知道有一件事,那就是演示文稿会将批次从初始开发改为部署。

如果你考虑一下,for循环真的不是逻辑,而是一个等距转换函数,如果你按照Separation of Concerns,那么你通过某种方法将数据传递给for循环。我建议测试for循环获取正确的数据,但不是for循环的输出。

如果您发现自己重复生成表格,那么一定要开始对这些表格模板进行单元测试。但再一次,您会发现这些模板会发生很多变化。

此时,您应该考虑将迭代与HTML输出分开,以帮助您在测试中将自己与这些问题区分开来。

一种方法是使用映射函数,它将获取列表和转换函数,并对列表中的每个项执行函数,然后返回转换后的列表。

通常,在创建表时,我最终会在创建一行时使用两个for循环。

  1. 遍历所有行。
  2. 在(1)中迭代行中的项目。
  3. 单元测试非常难看,但是使用闭包你可以创建函数生成器,实现起来真的很容易[实际上可以说是实现。]

答案 2 :(得分:3)

您可以使用PHPUnit。它有输出测试。

http://www.phpunit.de/manual/3.0/en/testcase-extensions.html

答案 3 :(得分:1)

PHPUnit有一个扩展,它在这里进行html验证:https://github.com/xvoland/html-validate

答案 4 :(得分:1)

我发现SimpleTest框架非常有用,通常我将它用于集成测试,PhpUnit用于单元测试。他们给了我很多手动提交的配方奶粉,我会一遍又一遍地做。

在进行此类集成测试时,我的习惯是遵循这一点:

  1. 尽量不要重复已经通过实际单元测试完成的测试。例如,如果您有针对电子邮件地址的经过单元测试的验证功能,则提交所有类型的无效电子邮件地址是没有意义的。只有在重定向时才会检查一次,并显示错误消息。
  2. 不要将生成的HTML与完整的参考输出进行比较,您必须在每次重新设计页面时更新测试。而是仅使用$webTestCase->assertText('...');$webTestCase->assertPattern('/.../');检查关键部分。
  3. 使用一些微小的辅助函数,您可以获得很多鲁棒性。以下函数将打开一个页面并检查页面是否成功打开而没有警告。由于没有可以在设计时发出警告的PHP编译器,因此至少可以确保代码不会产生错误或警告。

    public static function openPageWithNoWarnings($webTestCase, $page, $landingPage = null)
    {
      // check that page can be opened successfully
      $webTestCase->assertTrue($webTestCase->get($page));
    
      // check that there are no PHP warnings
      $webTestCase->assertNoPattern('/(warning:|error:)/i', 'PHP error or warning on page!');
    
      // check if landed on expected page (maybe a redirect)
      if (!empty($landingPage))
      {
        $url = $webTestCase->getUrl();
        $file = basename(parse_url($url, PHP_URL_PATH));
        $webTestCase->assertEqual($page, $file,
          sprintf('Expected page "%s", got page "%s".',  page, $file));
      }
    }
    

    这样的测试不会给你带来太多的工作,你可以从非常轻的测试开始,但只要点击一下鼠标就可以立即给你反馈。

答案 5 :(得分:0)

自己遇到这个问题。我认为一种方法可能是使用类似phpQuery的东西来使你的测试不那么脆弱。而不是测试确切的输出,测试输出中应该有某个地方的h3标签。如果它稍后被包装在一个div中,因为设计师需要增加额外的背景,或者因为一些ie6浮动bug的解决方法,那么你的测试仍然有效。

它不是很纯粹,但仍然是一个非常有用的工具。

答案 6 :(得分:0)

在某些情况下(例如CakePHP Helpers),类或函数的目的是为您生成一致的HTML。在这种情况下,测试HTML生成的单元的预期属性对于给定输入是否正确非常重要。在这种情况下,这个问题肯定是有效的。

PHPUnit为此提供了assertTag()函数。

然而要回应其他人;重要的是要强调单元测试应该在项目的最小可能组件上进行,而不是整个渲染的网页。还有其他工具(例如Selenium),旨在确保这些单个组件正确地集成

答案 7 :(得分:0)

一种非常简单的方法是使用输出缓冲。

例如

ob_start();
function_which_produces_some_output();
$this->assertEquals( ob_get_clean(), '<p>Expected Output Here</p>');

答案 8 :(得分:0)

其中许多链接已失效或陈旧。看看https://packagist.org/packages/phpfui/html-unit-tester根据w3.org标准验证HTML和CSS。

答案 9 :(得分:0)

许多此类链接已失效或陈旧。看看http://phpfui.com/PHPFUI/HTMLUnitTester,它已根据w3.org标准验证了HTML和CSS。我写它是因为找不到任何最近支持的PHP库来执行此操作。其他解决方案基于旧版本的PHPUnit或与现代PHP代码不兼容。

它使用W3C HTML验证程序服务,我建议在本地运行。所有这些都在配置的自述文件中进行了说明。该库的优点是它不执行实际的验证,而是调用W3C.org代码,因此,如果您保持本地安装最新,它将始终保持最新状态。

希望这会有所帮助。