DSL生成测试数据

发布于 2024-08-28 15:56:06 字数 1174 浏览 7 评论 0原文

有多种方法可以生成测试数据(不仅仅是单元测试),例如,Object Mother、构建器等。另一种有用的方法是将测试数据编写为纯文本:

产品:主要;价格:145、255;到期日期:2011 年 4 月 10 日;数量:2;包括:子
产品:子;价格:145、255;到期日期:2011 年 4 月 10 日;数量:2

然后将其解析为 C# 对象。这在单元测试中很容易使用(因为深层内部集合可以用单行编写),这在类似 FitNesse 的系统中使用起来更加方便(因为这种 DSL 自然适合 wiki),等等。

所以我就用这个,写解析器,但是每次都写,很繁琐。我不是 DSL/语言解析器方面的专家,但我认为它们可以在这里提供帮助。使用什么才是正确的?我只听说过:

  • DSL(我的意思是任何 DSL)
  • Boo(我认为可以做DSL)
  • ANTLR

,但我什至不知道该选择哪一个以及从哪里开始。

那么问题来了:使用某种DSL来生成测试数据是否合理?您建议这样做什么?有现成的案例吗?

更新:看来我还不够清楚。这与原始字符串到对象的转换无关。查看第一行并将其关联到

var main = Product.New("Main")
   .AddPrice(Price.New(145).WithType(PriceType.Main).AndQty(2))
   .AddPrice(Price.New(255).WithType(PriceType.Maintenance).AndQty(2))
   .Expiration(new DateTime(10, 04, 2011));
var sub =  Product
   .New("Sub").Parent(main)
   .AddPrice(...));
main.AddSubProduct(sub);
products.Add(main);
products.Add(sub);

并注意,我首先创建子产品,然后将其添加到主产品,即使它以相反的顺序列出。价格以特殊方式处理。我想指定子产品的名称并获取对其创建的引用。我想在单行上列出所有产品属性 - 平坦和非重复。我想使用属性的默认值。等等。

更新:我不相信要避免使用 DSL,因为所有替代示例都过于冗长且不方便用户使用。没有人说过任何有关 DSL 的有用信息。

There're several ways to generate data for tests (not only unit tests), for example, Object Mother, builders, etc. Another useful approach is to write test data as plain text:

product: Main; prices: 145, 255; Expire: 10-Apr-2011; qty: 2; includes: Sub
product: Sub; prices: 145, 255; Expire: 10-Apr-2011; qty: 2

and then parse it into C# objects. This is easy to use in unit tests (because deep inner collections can be written in single line), this is even more convenient to use in FitNesse-like system (because this DSL naturally fits into wiki), and so on.

So I use this and write parser, but it's tedious to write each time. I'm not a big expert in DSL/language parsers, but I think they can help here. What would be the right one to use? I only heard about:

  • DSL (I mean, any DSL)
  • Boo (that I think can do DSL)
  • ANTLR

but I don't even know which one to pick and where to start.

So the question: is it reasonable to use some kind of DSL to generate test data? What would you suggest to do so? Are there any existing cases?

Update: seems like I was not clear enough. It's not about raw string to object convertion. Look at first line and relate it to

var main = Product.New("Main")
   .AddPrice(Price.New(145).WithType(PriceType.Main).AndQty(2))
   .AddPrice(Price.New(255).WithType(PriceType.Maintenance).AndQty(2))
   .Expiration(new DateTime(10, 04, 2011));
var sub =  Product
   .New("Sub").Parent(main)
   .AddPrice(...));
main.AddSubProduct(sub);
products.Add(main);
products.Add(sub);

And note that I first create sub product and then add it to main, even though it is listed in reverse order. Prices are handled in a special way. I want to specify name of Sub product and get reference to it - created. I want to list all product properties - FLAT and NON-REPEATATIVE - on single line. I want to use defaults for properties. And so on.

Update: I'm not convinced to avoid DSL because all the alternative examples are too verbose and not user-friendly. And no-one said anything useful about DSL.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我的奇迹 2024-09-04 15:56:06

对于数据 DSL YAML 是一个很好的候选者。以下是来自 Wikipedia 的示例:

---
receipt:     Oz-Ware Purchase Invoice
date:        2007-08-06
customer:
    given:   Dorothy
    family:  Gale

items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      price:     100.27
      quantity:  1

bill-to:  &id001
    street: |
            123 Tornado Alley
            Suite 16
    city:   East Westville
    state:  KS

ship-to:  *id001

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.

我在多个项目中使用了 YAML,并且对此感到满意。

然而,如果我们谈论的是单元测试,那么使用构造函数和属性赋值“手动”构造必要的对象通常会更简单、更易读。这是因为单元测试本质上高度集中于某些代码(单元),并且创建足以用于测试的数据基础架构应该不难。在单元测试中对半完整的实体进行操作是可以的,不必费心构建与此具体测试无关的数据。

对于功能测试来说,YAML 非常有用。

For the data DSL YAML is an excellent candidate. Here is a sample from Wikipedia:

---
receipt:     Oz-Ware Purchase Invoice
date:        2007-08-06
customer:
    given:   Dorothy
    family:  Gale

items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      price:     100.27
      quantity:  1

bill-to:  &id001
    street: |
            123 Tornado Alley
            Suite 16
    city:   East Westville
    state:  KS

ship-to:  *id001

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.

I used YAML in several projects and happy with it.

However, if we are talking about unit-tests it is usually simpler and more readable to construct necessary objects “by hand” with constructors and property assignments in-place. This is because unit-test are by their nature highly focused on some code (unit), and it shouldn't be hard to create data infrastructure that is just enough for the test. It is OK to operate on half-complete entities in unit-tests, don't bother with constructing data that is not related to this concrete test.

For functional tests YAML is great.

在风中等你 2024-09-04 15:56:06

我首先会看看我选择的语言是否足够丰富来构建我的 DSL。 C# 应该很容易处理你的情况:

Product[] products = new Product[] {
    new TestProduct{product="Main", prices=new[]{145, 255}, Expire="10-Apr-2011", qty=2, includes="Sub"},
    new TestProduct{product="Sub", prices=new[]{145, 255}, Expire="10-Apr-2011", qty=2}
};

虽然不是那么漂亮,但绝对可以忍受,以至于我很难证明定制 DSL 的额外工作是合理的。

另请注意,Expire 是用字符串初始化的,但它显然是一个日期。这对于 DSL 习惯用法来说是完全合理的,因为 TestProduct.Expire 的 setter 可以进行转换。

I would first start by seeing if my language of choice was rich enough to build my DSL. C# ought to handle your case quite easily:

Product[] products = new Product[] {
    new TestProduct{product="Main", prices=new[]{145, 255}, Expire="10-Apr-2011", qty=2, includes="Sub"},
    new TestProduct{product="Sub", prices=new[]{145, 255}, Expire="10-Apr-2011", qty=2}
};

Not quite as pretty, but certainly tolerable enough that I would struggle to justify the extra effort of a custom DSL.

Also note that Expire is initialised with a string, but it is obviously a date. This is perfectly reasonable for a DSL idiom, since TestProduct.Expire's setter can do the translation.

紫瑟鸿黎 2024-09-04 15:56:06

对于创建外部 DSL,我会推荐 Eclipse TMF Xtext,它非常好(基于 ANTLR 但更简单),但构建在 Eclipse 和 Java 之上,但是您可以生成任何代码。
在创建测试数据时,我受到了 Ruby on Rails 人员的做法的启发,这是另一个答案中提到的 YAML 固定装置,但我也看到了一种使用工厂的方法,它可以帮助您摆脱一些口是心非、缺乏灵活性。看看这个 Railscasts 158:工厂而不是固定装置,它可能会给你一些想法用于设计 DSL。

For creating an external DSL I would recommend Eclipse TMF Xtext which is really good (based on ANTLR but simpler), but built on top of Eclipse and Java, however you can generate any code.
When it comes to creating testing data, I was inspired by the way the Ruby on Rails guys do it, which was YAML fixtures as mentioned in another answer, but I also saw an approach using factories, which can help you to get rid of some duplicity and inflexibility. Look at this Railscasts 158: Factories not Fixtures, it might give you some ideas for designing the DSL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文