【问题标题】:Testing Legacy PHP Spaghetti Code?测试旧版 PHP 意大利面条代码?
【发布时间】:2012-01-26 07:07:59
【问题描述】:

我从开发人员那里继承了一个相当大的、自制的 php4+MySQL 电子商务项目,他们在编写程序时自学了编程和 html。 (我会不寒而栗,除了他们能够从头开始做这么多事情真的令人印象深刻。)我的工作是维护它并使用新功能推动它。

代码的功能取决于$_SESSION 数据和其他全局状态结构,进而影响代码的流程以及站点的哪些部分通过require 语句显示。当我去年接手它时,我的第一个任务是将所有重复内容抽象到单独的文件中,这些文件通过require 语句包含在内,并从“显示”或输出代码中删除大部分“逻辑”代码,但我不能不要全部删除。我已经将代码移到了我可以使用的函数中,但这仍然非常有限。类和方法现在绝对是不可能的。

所有测试都是手动/视觉完成的。我想开始自动化一些测试,但我根本不知道从哪里开始。函数的单元测试非常简单,但很少有代码在函数中,而且大部分都非常简单。我看过phpUnitDbUnit,但所有关于它们的示例和讨论都集中在类和方法上。

那么,除了项目中最琐碎的部分之外,我还有哪些选择可以开始实施单元测试?

【问题讨论】:

  • 我的投票 - 进行非常增量的重构。
  • 顺便说一句,对于旧的 PHP 实现,着眼于保护您的数据库查询免受 SQL 注入。 “继承”项目时最容易被忽视的问题...
  • 您真的在运行 PHP4 服务器吗?它有 XDEBUG 可用吗?
  • 首先,祝你好运!我们有一个类似的系统,尽管我们已经设法通过少量的 OO 代码至少将其安装到 PHP 5.3 上。我的建议是买这本书:informit.com/store/product.aspx?isbn=0131177052。它主要基于 OO,但 IIRC 有一节是关于程序代码的,它是必不可少的阅读材料。稍加思考即可将许多技巧应用于过程代码。
  • 谢谢大家。我今天花了 PHPUnit + Selenium 设置和工作,我几乎对潜力垂涎三尺。我会在假期后发表更多评论并选择答案。

标签: php unit-testing phpunit legacy


【解决方案1】:

我可能会开始使用 Watir 或 Selenium 之类的工具进行测试。这将允许您自动对整个页面进行黑盒测试。一旦设置了这些测试,就可以开始重构 PHP 页面,并在重构时构建单元测试。

【讨论】:

  • 短而甜; Selenium 正是我所需要的,特别是因为我的团队的其他成员会发现 Firefox IDE + PHP 输出非常平易近人。
【解决方案2】:

没有单元测试的遗留代码总是很痛苦。没有真正的解决方案,因为大多数时候代码根本不是以可单元测试的方式编写的。在工作中,我们也必须处理大量遗留代码。我们为新编写的代码编写了单元测试(这也很痛苦,因为您需要能够设置一些测试数据和类似的东西)。这样它就不会变得更糟,并且您将覆盖在新代码中调用的越来越多的旧遗留代码。这样做你每次都会更接近单元测试所涵盖的代码。

【讨论】:

    【解决方案3】:

    你面临着一项艰巨的任务。您可能无法在任何合理的时间内编写所有需要的测试代码,而且您的经理不会关心您是否这样做,如果他们认为应用程序大部分工作正常。

    您应该专注于为修改 应用程序代码构建测试。如果您的应用程序有生命力,将会有很多内容让您忙碌。

    你应该 还要验证您是否实际上在测试新代码。通过将新签入(您正在使用源代码控制,对吗?如果没有,请先修复!)与旧签入进行比较,您可以查看更改的内容并获取有关更改位置的精确位置信息。您(嗯,您的经理应该)想要证明这些更改已经过测试。您可以使用代码覆盖工具来判断已测试的内容,并将其与新更改的位置相交;交叉点最好包含所有修改后的代码。 我们的PHP Test Coverage 可以提供覆盖信息,并且可以计算这样的交叉点数据。

    【讨论】:

      【解决方案4】:

      首先PHPUnit可以用来测试程序代码就好了。不要让 PHPUnit 示例仅显示类这一事实阻止您。这就是 PHPUnit 测试的组织方式。

      您可以只编写测试类并从中测试您的函数而没有任何问题,这应该是您最小的问题:)

      如果代码不能在 PHP 5.2+ 上运行,那么您就不能使用当前的 PHPUnit 版本,这绝对是一个值得关注的问题,我的第一个一般性建议是找出 PHP 5 升级可能带来的任何问题。


      开始推荐一本书,为您省去一些麻烦:

      Working Effectively with Legacy Code

      本书将帮助您避免许多您必须自己犯一次的小错误,并让您拥有正确的心态。它是基于 Java 的,但这并不是一个真正的问题,因为大多数东西都很容易适应。


      测试很困难,因为你甚至不知道应用程序首先应该做什么

      让单元测试运行起来需要相当长的时间,并且不会给你一个“它还在工作吗”的状态,所以我的第一点是设置一些集成和前端测试。

      Selenium 之类的工具和Behat 的网络测试部分可以在这方面为您提供很多帮助。

      使用 Behat 的优势在于您可以为产品实际应该做什么编写精美的文档。无论项目如何进行,这些文档始终对您具有价值

      其余的内容如下:“当我转到此 url 并输入应创建的用户数据时,当我点击那里时,我会收到一封包含我的数据导出的电子邮件”。看看这个。可能有用。


      最重要的是如果事情还在工作,快速获得绿色/红色指示灯!

      如果你发现它被破坏了,尽管你的“灯”是绿色的,你可以从那里扩展测试。


      如果你不知道它什么时候坏了,你就永远不会有足够的信心去改变足够多的东西,这样你就可以逐步改进需要修复或改变的地方。


      在您大致了解一切是如何工作的并且您相信您的小测试会在您破坏“整个事情”时向您展示,我会说是时候设置一个小型 Continuous integration 服务器,如 Jenkins 用于PHP 允许您随时间跟踪项目的状态。您一开始不需要所有 QA 的东西(也许是为了了解项目的概况),但只是看到所有“它仍然有效”的东西都返回“是”是非常重要的,并且可以为您节省大量时间以确保手动的。

      2% 的代码覆盖率很无聊

      当您处于单元测试和代码覆盖率发挥作用的地步时,您将面临平均读取率为 0%。从来没有看到这个数字大幅上升,这很烦人。

      但您想确保测试新代码,所以我建议使用 PHP_Change_Coverage 作为 described in this blog posting,因此请确保您接触的所有内容都经过测试。

      PHP 黑魔法

      function stuff() {
          if(SOME_OLD_UGLY_CONST == "SOME SETTING") {
               die("For whatever reasons");
          }
          return "useful stuff";
      }
      

      当您的脚本die() 进行测试时,它真的很烦人,但该怎么办?

      在没有测试的情况下重新编写所有脚本可能比不做任何事情更有害,所以也许你想先破解测试。

      为此,另一种解决可怕事情的方法是 php test helpers 扩展。

      <?php
      set_exit_overload(function() { return FALSE; }
      exit;
      print 'We did not exit.';
      unset_exit_overload();
      exit;
      print 'We exited and this will not be printed.';
      ?>
      

      【讨论】:

      • 博客发布链接不是博客发布。另一个链接是 selenium 而不是 PHP_Change_Coverage。
      • @hakre 感谢您指出这一点。弄乱了链接。修复它:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      相关资源
      最近更新 更多