如何成为效率达人:更有效地测试PHP代码

2022-10-11 21:24:33 158 0
魁首哥

质量代码在PHP社区中受到高度重视。 你很少会在GitHub上找到未经测试的库。 开发人员在测试过程中遇到的两个问题是处理文件操作,以及测试内置的PHP函数,如time()orexec()以满足某些期望。 在这篇文章中,解释了这些案例的一些解决方案。

作为一名PHP开发人员,您可以轻松进入使用文件或与文件进行交互的情况,特别是在处理上传的文件或写入 缓存 或日志文件时。 作为一名优秀的开发人员,您还希望通过测试来涵盖此程序流程。

清单1显示了aCacheWarmer类的简化示例,该示例在warmUp方法中创建缓存目录(如果它尚不存在)。

private $cacheDirectory; public function __construct(string $cacheDirectory) { $this->cacheDirectory = $cacheDirectory;

}

public function warmUp()

{

if (!is_dir($this->cacheDirectory) &&!mkdir($this->cacheDirectory)) {

throw new \RuntimeException(‘Could not create cache directory!’);

}

// …

}

}

如果你想在单元测试的帮助下测试这样一个类,最简单的方法就是直接在文件系统中完成。该类在本地进行初始化,调用thewarmUpmethod,系统在最后检查相应的目录是否已创建并正确填充。虽然这种方法很快且非常有效,但确实涉及各种可能的问题。例如,如果您正在使用除实际目标系统以外的操作系统,则测试人员和开发人员必须牢记这一点。确保测试之后正确清理文件系统也很重要 – 一方面要避免依赖测试中的副作用,另一方面要防止自己的文件系统被测试数据淹没。

检查此类应用程序的更好的解决方案是使用虚拟文件系统。虚拟文件系统是作为PHP的独立流包装器创建的。这可以使用内置的PHP函数,例如mkdirorfile_exist。 vfsStreamlibrary提供这一点。一个优点是vfsStream可以用于几乎任何PHP测试框架,例如PHPUnit。 composer 的安装过程与往常一样完成:

composer需要-dev mikey179 / vfsStream

现在,要测试的文件系统在测试完成后才会流式传输和丢弃。这有很大的好处,你不必担心清理和测试的副作用。更好的I / O操作性能也可以在大型测试套件中发挥作用。清单2显示了使用PHPUnit和vfsStream的ourCacheWarmer类的可能测试。

root = vfsStream::setup();

}

/**

* @test

*/

public function canCreateCacheDirectoryOnWarmUp()

{

$cacheWarmer = new CacheWarmer($this->root->url() . ‘/cache’);

$cacheWarmer->warmUp();

$this->assertTrue($this->root->hasChild(‘cache’));

}

}

该库还有许多其他有用的功能,例如权限处理和可调整的磁盘配额。 但是,也应该考虑到这些限制。 例如,与符号链接的交互是不可能的。 更多的文档和例子可以在项目的官方Wiki中找到。

测试内置的PHP函数

作为PHP开发人员经常遇到的另一个问题是使用像time()or exec ()这样的内置PHP函数。 这些通常很难测试。 清单3显示了aPdfCreator类的简化版本,它使用wkhtmltopdfinternally创建PDF并通过exec()函数执行它。

namespace My\App;

class PdfCreator

{

// …

public function execute(string $html file , string $pdfFile)

{

$output = [];

$returnValue = 0;

exec(sprintf(‘/usr/ bin /wkhtmltopdf %s %s’, $htmlFile, $pdfFile), $output, $returnValue);

if ($returnValue !== 0) {

throw new \RuntimeException(‘Could not create PDF file!’);

}

return $output;

}

// …

}

当然,这个过程可以用适当的软件架构绕过。但是,这并非总是可行的。如果您仍然想确保应用程序正确处理内置PHP函数的返回值,可以采用几种方法来完成此操作。

单位而不是 集成测试

第一个常常是显而易见的变体是用功能或集成测试来覆盖这个变体。在这种情况下,您可以在特定条件或上下文下直接执行应用程序,并相应地检查结果。但是,这些测试通常非常耗时,因为每次都必须准备或初始化测试环境。

为了直接测试内置PHP函数的期望,我们可以使用php-mock。该工具还支持各种测试框架,如PHPUnit或Prophecy(phpspec)。模拟内置PHP函数php-mock使用PHP的命名空间备用规则。它表示,如果使用内置的PHP函数设置为不合格(不带前导反斜杠),则首先在自己的名称空间中搜索使用的内置PHP函数。只有在这之后,才能从全局命名空间获取函数。

PHPUnit的php-mock版本也可以通过Composer安装:

composer需要-dev php-mock / php-mock-phpunit

对于测试,php-mock提供了一个特性,以便我们已经显示的PDFCreatorclass的可能测试看起来如清单4所示。

Listing 4

getFunctionMock(‘My\App’, ‘exec’);

$exec->expects($this->once())->willReturnCallback(

function ($command, &$output, &$returnValue) {

$this->assertEquals(‘/usr/bin/wkhtmltopdf file.html file.pdf’, $command);

$output = [‘failure’];

$returnValue = 1;

}

);

$pdfCreator = new PdfCreator;

$pdfCreator->execute(‘file.html’, ‘file.pdf’);

}

}

这样简单的单元测试显然有很大的优势。 但缺点是你必须确切知道哪些返回值是可能的。 否则,尽管测试覆盖范围广泛,但仍可能发生错 另一个小缺点是已经提到了对非限定函数调用的限制。 但是这些可以在你自己的代码中轻松设置。

结论和展望

乍一看,最明显的测试程序有时是最大的缺陷。 使用大量测试套件时尤其如此。 在这种情况下,这里介绍的两个库在避免缓慢的集成测试并用单元测试替代它们时可以作为真正的效率助手。 出于这个原因,开发人员应始终记住这一选项。

收藏
分享
海报
0 条评论
158
上一篇:MySQL面试题集锦,据说国内外知名互联网公司都在用 下一篇:【Api】PHP与微信公众号支付,很简单

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码