【发布时间】:2010-09-10 21:34:06
【问题描述】:
在用 JavaScript 开发 UI 时,我很难找到正确遵循 TDD 原则的最佳方法。解决这个问题的最佳方法是什么?
最好将视觉与功能分开吗?您是否先开发视觉元素,然后编写测试,然后编写功能代码?
【问题讨论】:
标签: javascript user-interface tdd
在用 JavaScript 开发 UI 时,我很难找到正确遵循 TDD 原则的最佳方法。解决这个问题的最佳方法是什么?
最好将视觉与功能分开吗?您是否先开发视觉元素,然后编写测试,然后编写功能代码?
【问题讨论】:
标签: javascript user-interface tdd
这是我切换到 Google Web Toolkit 的主要原因……我使用 Java 进行开发和测试,并且合理地期望编译后的 JavaScript 能够在各种浏览器上正常运行。由于 TDD 主要是一个单元测试功能,所以大部分项目可以在编译和部署之前进行开发和测试。
集成和功能测试套件验证生成的代码在部署到测试服务器后是否按预期运行。
【讨论】:
我从未成功 TDDed UI 代码。我们最接近的确实是尽可能地将 UI 代码与应用程序逻辑分开。这就是模型-视图-控制器模式有用的原因之一 - 模型和控制器可以在没有太多麻烦和过于复杂的情况下进行 TDD。
根据我的经验,视图总是留给我们的用户接受测试(我们编写 Web 应用程序,我们的 UAT 使用 Java 的 HttpUnit)。然而,在这个级别上,它实际上是一个集成测试,没有我们希望的 TDD 的隔离测试属性。由于这种设置,我们必须先编写控制器/模型测试/代码,然后是 UI 和相应的 UAT。然而,在我最近编写的 Swing GUI 代码中,我一直在编写带有存根的 GUI 代码来探索我的前端设计,然后再添加到控制器/模型/API。不过这里是 YMMV。
所以重申一下,我能给出的唯一建议是您似乎已经怀疑的 - 尽可能将您的 UI 代码与您的逻辑分开并进行 TDD。
【讨论】:
我即将开始在我正在从事的一个新项目上执行 Javascript TDD。我目前的计划是使用qunit 进行单元测试。在开发测试时,只需在浏览器中刷新测试页面即可运行。
为了持续集成(并确保测试在所有浏览器中运行),我将使用Selenium 在每个浏览器中自动加载测试工具,并读取结果。这些测试将在每次签入源代码控制时运行。
我还将使用JSCoverage 来获取测试的代码覆盖率分析。这也将通过 Selenium 自动执行。
我目前正在设置它。设置完成后,我将使用更准确的详细信息更新此答案。
测试工具:
【讨论】:
我过去用 Javascript 做过一些 TDD,我必须做的是区分单元测试和集成测试。 Selenium 将测试您的整个站点,包括服务器的输出、它的回发、ajax 调用等等。但对于单元测试,这些都不重要。
您想要的只是要与之交互的 UI 和脚本。您将为此使用的工具基本上是JsUnit,它接受一个HTML 文档,页面上有一些Javascript 函数并在页面上下文中执行它们。所以你要做的就是在你的函数中包含页面上的 Stubbed out HTML。从那里,您可以测试脚本与模拟 HTML、脚本和测试的隔离单元中的 UI 组件的交互。
这可能有点令人困惑,所以让我们看看我们是否可以做一个小测试。让一些 TDD 假设在加载组件后,元素列表会根据 LI 的内容进行着色。
tests.html
<html>
<head>
<script src="jsunit.js"></script>
<script src="mootools.js"></script>
<script src="yourcontrol.js"></script>
</head>
<body>
<ul id="mockList">
<li>red</li>
<li>green</li>
</ul>
</body>
<script>
function testListColor() {
assertNotEqual( $$("#mockList li")[0].getStyle("background-color", "red") );
var colorInst = new ColorCtrl( "mockList" );
assertEqual( $$("#mockList li")[0].getStyle("background-color", "red") );
}
</script>
</html>
显然,TDD 是一个多步骤的过程,因此为了进行控制,我们需要多个示例。
yourcontrol.js(步骤 1)
function ColorCtrl( id ) {
/* Fail! */
}
yourcontrol.js(步骤 2)
function ColorCtrl( id ) {
$$("#mockList li").forEach(function(item, index) {
item.setStyle("backgrond-color", item.getText());
});
/* Success! */
}
您可能会看到这里的痛点,您必须在页面上保持您的模拟 HTML 与您的服务器控件的结构同步。但它确实为您提供了一个很好的使用 JavaScript 进行 TDD 的系统。
【讨论】:
【讨论】:
我发现MVP 架构非常适合编写可测试的 UI。您的 Presenter 和 Model 类可以简单地进行 100% 单元测试。您只需要担心用于 UI 测试(使用 Selenium 等)的 View(它应该是一个愚蠢的薄层,只会向 Presenter 触发事件)
请注意,我说的是完全在 UI 上下文中使用 MVP,而不必跨越到服务器端。您的 UI 可以有自己的 Presenter 和 Model,它们完全位于客户端。 Presenter 驱动 UI 交互/验证等逻辑,而 Model 保留状态信息并提供到后端的门户(您可以在其中拥有单独的 Model)。
您还应该看看Presenter First TDD 技术。
【讨论】:
我所做的是戳 Dom 看看我是否得到了我所期望的。这样做的一个很好的副作用是,在加快测试速度的同时,您也可以加快应用速度。
我刚刚发布了一个开源工具包,它将极大地帮助 JavaScript tdd。它是许多开源工具的组合,可为您提供开箱即用的 requirejs 主干应用程序。
它提供单个命令来运行:dev web server、jasmine 单浏览器测试运行器、jasmine js-test-driver 多浏览器测试运行器,以及 JavaScript 和 CSS 的连接/缩小。它还输出应用程序的未缩小版本以进行生产调试,预编译您的车把模板,并支持国际化。
无需设置。它只是工作。
【讨论】: