我需要为用Java编写的应用程序生成黄瓜测试用例。
测试用例如下:
Scenario My great test
Given the following input
"""
Code snippet of a DSL
"""
And the following data
| name | type | value |
| a | Boolean | true |
| b | Integer | 5 |
When I run the evaluation
Then the result should be "Yay!"
我创建了类似于这种结构的数据类型作为语法树以及一个“后端”,它将采用语法树并创建测试用例字符串。
数据类型如下:
data TestCase = Scenario String DslStatement DataStatement ResultStatement
data DslStatement = Dsl [TopLevelStatement]
data TopLevelStatement =
StatementTypeA String
| StatementTypeB String
| StatementTypeC String SubStatementTypeA [SubStatementTypeB]
| StatementTypeD String [String]
...
等等。
现在我想使用不同的值和类型以及内容生成大量的这些数据结构。
我可以编写带有必要参数的函数,并创建一个语法树,其中的参数值应该出现在它们应该出现的位置。但是,由于测试用例中包含的DSL一直在变化(它是逐步开发的),我将不得不改变所有创建不同测试用例类型的函数,这很乏味。此外,测试用例可以基于标准语法树,只在少数几个测试用例的地方修改。
我现在的想法是创建或多或少类似于Java中具有流畅界面的构建器模式的函数。从标准语法树开始,我创建了修改它的函数,并返回结果树以进行进一步修改,如下所示:
withName :: String -> TestCase -> TestCase
withName name (Scenario _ dsl data result) = Scenario name dsl data result
withResult :: ResultStatement -> TestCase -> TestCase
withResult result (Scenario name dsl data _) = Scenario name dsl data result
...
然后我应该能写出这样的东西:
withName "My Test Case" . withResult (Result "Yay!") $ createStandardTestCase
只要dsl更改,只需要修改构建器函数和后端,以便调整我的测试用例。
这是解决问题的可行/有效方法吗? 有没有更好的创建这种语法树的想法?
THX!
- 的Mathias
答案 0 :(得分:1)
在Haskell中,流畅的接口模式称为Endo
。它是Monoid
,因此您可以使用mconcat
获得一些效率,但我很少看到Endo
在实践中使用,因为它不是一个巨大的收获。
对于这样的定义,您将面临的一个挑战是需要默认的所有内容,毕竟withName "My Test Case"
本身需要一个有效的TestCase
。这可能意味着您的许多类型将是Maybe
或者它可能只是意味着您需要仔细定义类型。这可能与您的标准语法树的概念有关。
创建这种可扩展AST的全功能方法是使用Data types a la carte技术。简而言之,您定义了一个通用的“sum”类型运算符,然后构建了对递归类型的某些组件进行操作的函数。通过具有聪明的默认值,您可以省略许多样板定义并允许可扩展性。
此类技术可能对您的类型有用。
最后,很难谈论像这样的嵌套数据类型,而不是通过Control.Lens
(包括所有可能的电池)或fc-labels
(更简单)来讨论透镜的建议。这些让您可以对您的树进行深入检查,可以双向使用,以查看和构建更新Endo
。它们还具有聪明的通用原则,例如能够同时“关注”树中的多个位置(这些是Fold
中的Traversal
和Control.Lens
。)