是否有一个lint风格的工具,将检查freemarker模板的模板错误?

时间:2012-02-01 05:24:49

标签: java freemarker lint

我们一直遇到模板错误偶尔潜入我们的生产网站的问题,所以如果有一个工具来捕获这些,我很乐意将它添加到我们的部署过程中。

3 个答案:

答案 0 :(得分:3)

根据我的经验,Freemarker在尝试渲染模板时实际上只有两类错误(忽略配置):

  • 模板级别的简单语法错误
  • 关于在Java级别传入的模型的假设不正确

尽管linting工具通常会在代码中发现错误,但lint工具并不能代替基本测试,这对于您在此处遇到的问题来说是一个更好的解决方案,因为您在生产代码中看到异常。

无论好坏,Freemarker关于谁在使用数据以及谁在使用标记的假设都是具有不同技能组的不同人。假设情况确实如此(并且您可以使用Java工程资源),从测试过程的角度来看,您有两种方法可以解决此问题(尽管要真正严格,但您需要两者)。

前端测试

在我之前的工作中,我们自己使用了这种方法。基本上,前端工程师会在特殊的Web前端攻击模板,其中编辑的模板直接位于包含两个列表的配置路径上:

  • 要渲染的模板
  • 要呈现的数据模型的版本

'版本'本质上是一组两层硬编码的Java对象,其中第1层在所有模板中都是一致的,而第2层是模板特定的变体。因为我们的大多数电子邮件都是帐户级别的通知,所以我们获得了很多里程并且只使用全局数据模型就可以重复使用,而且我们很少需要深入研究这些小东西。

<强>优势

  • 前端工程师永远不需要接触Java,因此如果您的团队拥有的话,您可以将HTML / CSS专家用于预期目的
  • 后端工程师可以根据模板及其构造回收大量内容
  • 在引用经常使用的值(例如“account”)时,松散地强制执行数据模型变量名称的统一性(前端工程师会因为他们预期的值不存在而感到恼火,因为不同的后端工程师将某些内容命名为“错误”)< / LI>

不太好

  • 这基本上是手动测试,并且在某些时候将无法捕获错误

后端测试

另一种选择是在创建每个模板时对其进行单元测试。因为Freemarker中的异常都发生在编译时,所以您只需要执行以下操作(完成初始设置后):

Template temp = cfg.getTemplate("myTestedTemplate.ftl");
temp.process(myTestDataModel, myIgnoredOutput); // No exceptions -> OK for us

请注意,在这种情况下你不关心结果,你只需要编译它。这很重要,因为在Java中调试编译输出时很容易陷入困境而不能解决当前问题。和以前一样,您也希望在这里进行相同的两层单元测试:

  • 使用一些通用模型对所有模板进行冒烟测试(可以通过编程方式完成每个模板)
  • 使用您期望的数据模型中的变体测试单个模板(缺少设置,不完整的字段等)

<强>优势

  • 构建/部署过程的一部分,因此您可以消除模板中的人为错误
  • 根据您使用Freemarker的方式,如果您还没有这样做,也可以验证其他流程是否正确生成了数据模型

<强>不那么好

  • 前端工程师需要阅读堆栈跟踪以找出失败的原因
  • 使用此方法进行开发最终会与您的构建过程联系起来,而这个过程远不如重新加载页面那么快

如果您有时间同时执行这两项操作,我建议您使用单元测试来处理边缘情况以及弹出时发现的其他问题,然后开发Web前端以便开发页面不会需要重新编译。版本前端的功能非常有用,但目标是首先防止生成错误到构建过程。启动,然后优化和全部。

答案 1 :(得分:1)

如果您的意思是运行时输出错误而不是模板语法错误,您可以使用一组(脆弱的)“期望获得”集成测试。这有多合适取决于模板的复杂程度以及模板的动态性。如果您只想进行一些简单的“冒烟”测试,这可能是一个很好的解决方案。

对于每个模板,至少创建一个测试。使用具体/静态/预先指定的输入数据和具体/静态/预先指定的输出结果。此输出必须在任何更改后第一次手动生成和验证,但从那时起,它可以保存并且可以编写测试脚本。如果模板拉入自己的数据(如日期等),这些数据无法设置为固定输入,则屏蔽或从预期输出中删除它。每个自动化测试应该:

  1. 从每个模板的至少一组输入数据生成“got”输出。
  2. 从输出中屏蔽或删除不可预测的变量区域。
  3. 将此“获取”结果与保存的预先验证的“预期”输出进行比较。
  4. 报告这些不一样时的失败。
  5. 确切的输出相等是最容易实现的并且确保正确。如果需要,每个模板都有多个测试。我不会试图聪明,只是让计算机做无聊和重复的工作。我会忽略在第一次传递时需要屏蔽的模板部分(一些测试比没有测试更好)。稍后当你决定提高可靠性以获得足够的价值时(或者过去曾经做错的任何事情),只为他们编写明确的测试。

    此解决方案有以下注意事项。

    1. 范围太大。对模板或数据模型中的任何内容进行的任何更改都可能需要更新测试。使用“diff”可能有助于手动验证并确定在数据模型和/或模板更改时如何修改测试。

    2. 代码拒绝和模块化导致测试问题。使用良好的模块化代码,一次代码更改可能会影响所有模板中的数据,但静态测试需要在发生这种情况时单独更改和重新验证所有测试。解决这个问题并不多,所以代码越好越模块化,导致的工作就越多:(

    3. 复杂的模板很难测试。仅使用几组静态数据来获得良好的模板覆盖可能会有问题。这可能意味着模板做了太多的“处理”,并没有真正用作模板。无论如何,这可能不是一个好主意。

答案 2 :(得分:-1)

我不知道有哪个工具可以帮到您,但是为了捕获语法错误,您所要做的就是将所有模板文件提供给new Template("whatever", theTemplateFileReader);。遗憾的是,您无法以这种方式检测运行时错误,例如对非存在变量/宏/导入的引用。为此,您可以调用Template.process,但如果没有实际应用程序中的数据模型,那么它当然没有意义。