使用 UI 驱动程序进行 BDD 测试(例如用于 Web 应用程序的 Selenium)

发布于 2024-10-10 02:48:22 字数 393 浏览 7 评论 0原文

BDD(行为驱动设计)测试可以使用 UI 驱动程序来实现吗?

例如,给定一个 Web 应用程序,而不是:

  • 为后端编写测试,然后在前端用 Javascript 编写更多测试

我应该:

  • 将测试编写为 Selenium 宏,在实际中模拟鼠标单击等浏览器?

我认为这样做的优点是:

  • 测试是用一种语言而不是多种语言编写的
  • 他们专注于 UI,这让开发人员从外到内思考
  • 他们在真正的执行中运行环境(浏览器),它允许我们
    • 测试不同的浏览器
    • 测试不同的服务器
    • 深入了解实际性能

有想法吗?

Can BDD (Behavior Driven Design) tests be implemented using a UI driver?

For example, given a web application, instead of:

  • Writing tests for the back-end, and then more tests in Javascript for the front-end

Should I:

  • Write the tests as Selenium macros, which simulate mouse-clicks, etc in the actual browser?

The advantages I see in doing it this way are:

  • The tests are written in one language, rather than several
  • They're focussed on the UI, which gets developers thinking outside-in
  • They run in the real execution environment (the browser), which allows us to
    • Test different browsers
    • Test different servers
    • Get insight into real-world performance

Thoughts?

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

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

发布评论

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

评论(7

浅浅 2024-10-17 02:48:22

我们使用 WPF 测试工具 (WipFlash) 并编写 NUnit 对 C# 应用程序完成了此操作以类似 BDD 的方式进行测试。

例如

Given.TheApplicationWindowIsOpen();
When.I.Press.OKButton();
The.Price.ShouldBeCalculated();

,不用说,我们必须自己编写大量 DSL 代码。但它成为企业/客户可读的解决方案。

We've done this for a C# application using a WPF testing tool (WipFlash) and writing NUnit tests in a BDD-like fashion.

e.g.

Given.TheApplicationWindowIsOpen();
When.I.Press.OKButton();
The.Price.ShouldBeCalculated();

We had to code a lot of the DSL ourselves, needless to say. But it becomes a business/customer readable solution.

萌能量女王 2024-10-17 02:48:22

尝试将 SpecFlow 与 WatiN 结合使用:(我不确定您是否在此处使用 .NET)

http://msdn.microsoft.com/en-us/magazine/gg490346.aspx

Try using SpecFlow with WatiN: (I'm not sure if you're using .NET here)

http://msdn.microsoft.com/en-us/magazine/gg490346.aspx

屋顶上的小猫咪 2024-10-17 02:48:22

对于 Web 测试,您可以尝试 WebDriver。 Selenium 团队目前正忙于集成 WebDriver。来自 Google 的 Simon Stewart 创建了 WebDriver,在博客中介绍了 WebDriver 的不同工作方式< /a> 到硒。

WebDriver 针对每个浏览器使用不同的技术。对于 Internet Explorer,WebDriver 使用 Microsoft 的 UI 自动化 - 与 @Brian Agnew 的 WipFlash 所使用的技术相同提到的是有根据的。这与假装点击按钮非常接近。 Simon 的博客展示了为什么这种方法比 Selenium 的 Javascript 解决方案更强大。

WebDriver 可从 Selenium 站点获取,但尚未作为 Selenium 的一部分完全实现。

For web testing, you could try WebDriver. The Selenium team are busy integrating WebDriver at the moment. Simon Stewart from Google, who created WebDriver, blogged here about how it works differently to Selenium.

WebDriver uses different technologies for each browser. For Internet Explorer, WebDriver uses Microsoft's UI automation - the same technology on which WipFlash which @Brian Agnew mentioned is based. This is as close as you'll get to pretending to click buttons. Simon's blog shows why this approach can be more powerful than Selenium's Javascript solution.

WebDriver is available from the Selenium site but hasn't been fully implemented as part of Selenium yet.

小梨窩很甜 2024-10-17 02:48:22

对于 BDD 和任何用例驱动的测试,能够传达测试正在做什么非常重要。许多测试套件的问题在于,编写后没有人完全确定测试到底在做什么。如果您使用非专业语言编写,这种情况会经常出现。专业化并不一定意味着一种特殊的语言,而是一种语言的足够抽象,这样就可以清楚地了解正在发生的事情。

例如,很多测试都有这样的代码(伪代码,我不会选择任何特定的框架):

object = createBrowser()
response = object.gotoURL( "http://someurl.com" );
element = response.getLink( "Click Here" );
response = element.doClick();

这对于某人来说很难快速转换为业务驱动程序(可能是产品经理,或用户)。相反,您想要创建专门的函数,或者如果您喜欢冒险的话,您可以创建一种语言,因此您可以这样:

GotoURL http://someurl.com/
Click link:Click Here

Selenium 及其宏或接口在这方面仍然相当低级。如果您确实使用它们,那么至少在它们周围构建一些包装器。

您当然也可以使用名为 TestPlan 的产品。它的后端有 Selenium,并公开了高级 API 和用于测试的自定义语言。它还不仅仅限于网络,还包括电子邮件、FTP 等。上面的示例语言是一个测试计划片段

For BDD, and any use-case driven tests, it is important to be able to communicate what a test is doing. The problem with many test suites is that post-writting nobody is quite certain exactly what the test is doing. This will come up very often if you write in a non-specialized language. Specialization doesn't necessarily mean a special language, but just enough of an abstraction in the one language so it is clear what is happening.

For example, a lot of tests have code that looks like this (pseudo-code, I won't pick on any particular framework):

object = createBrowser()
response = object.gotoURL( "http://someurl.com" );
element = response.getLink( "Click Here" );
response = element.doClick();

This is hard for somebody to quickly translate to a business driver (product manager perhaps, or user). Instead you want to create specialized functions, or a language if you're adventurous, so you can have this:

GotoURL http://someurl.com/
Click link:Click Here

Selenium, and its macros or interface, are still fairly low-level in this regards. If you do use them then at least build some wrappers around them.

You can of course also use a product called TestPlan. It has Selenium in the back-end and exposes a high-level API, and a custom langauge for testing. It also goes beyond just the web to included Email, FTP, etc. The sample language above is a TestPlan snippet

不疑不惑不回忆 2024-10-17 02:48:22

如果这对某人有帮助,我为此目的编写了一个驱动程序构建器库:
https://github.com/morsh/driver-pattern

BDD 壮举。司机及构建器模式

使您能够像这样编写驱动程序:

describe("<ToDoList />", () => {
  const driver = createDriver(Component, {
    getters: {
      todoItems: 'todo-item',
      addButton: 'add-button',
      todoTitle: (index: number) => screen.queryAllByTestId('todo-item')[index],
      deleteButton: (index: number) => screen.queryAllByTestId('delete-button')[index],
    },
    actions: get => ({
      clickAdd: () => fireEvent.click(get.addButton()),
      clickDelete: (index: number) => fireEvent.click(get.deleteButton(index)),
    }),
    createStore,
  });

  beforeEach(() => {
    drive.initialize()
  });

  it("should display list of todo items", () => {
    const todos = someTodoItems();
    driver.givenState.todos(todos).when.render();
    expect(driver.get.todoItems()).toHaveLength(todos.length);
  });

  it("should click on add", () => {
    const onClickSpy = jest.fn();
    driver.given.onClick(onClickSpy).when.render();
    expect(onClickSpy).toHaveBeenCalled();
  });
});

If this would help someone, I've written a driver builder library for that purpose:
https://github.com/morsh/driver-pattern

BDD feat. Driver & Builder Patterns

Which enabled you to write your driver like this:

describe("<ToDoList />", () => {
  const driver = createDriver(Component, {
    getters: {
      todoItems: 'todo-item',
      addButton: 'add-button',
      todoTitle: (index: number) => screen.queryAllByTestId('todo-item')[index],
      deleteButton: (index: number) => screen.queryAllByTestId('delete-button')[index],
    },
    actions: get => ({
      clickAdd: () => fireEvent.click(get.addButton()),
      clickDelete: (index: number) => fireEvent.click(get.deleteButton(index)),
    }),
    createStore,
  });

  beforeEach(() => {
    drive.initialize()
  });

  it("should display list of todo items", () => {
    const todos = someTodoItems();
    driver.givenState.todos(todos).when.render();
    expect(driver.get.todoItems()).toHaveLength(todos.length);
  });

  it("should click on add", () => {
    const onClickSpy = jest.fn();
    driver.given.onClick(onClickSpy).when.render();
    expect(onClickSpy).toHaveBeenCalled();
  });
});

家住魔仙堡 2024-10-17 02:48:22

您当然可以通过这种方式进行一些验收测试,但我认为大多数 BDD 倡导者不会建议在所有测试中都使用这种方法。当然,真正的 BDD 拥护者不会称它们为测试...

RSpec 书 提倡两级循环,首先编写验收测试(或场景)(主要在 Cucumber 中),并且在更类似于传统 TDD 的内部循环中编写单元测试(在 RSpec 中)。

验收测试的外循环还可以使用像 Selenium 这样的工具通过 UI 来驱动整个应用程序(The RSpec Book 的作者用了一章的时间来介绍这一点)。但它不适合单元测试。

通过 UI 执行整个应用程序的测试更难重复,并且往往比单元测试更慢、更脆弱。

You can certainly do some of your acceptance tests this way, but I think most BDD advocates would not advise using this for all tests. And of course, true BDD advocates wouldn't call them tests...

The RSpec Book advocates a two-level cycle with acceptance tests (or Scenarios) written first (primarily in Cucumber), and unit tests written (in RSpec) in an inner cycle more resembling the traditional TDD.

The outer cycle of acceptance testing can also use tools like Selenium to drive the entire application through the UI (and the authors of The RSpec Book spend a chapter on this). But it is not appropriate for unit tests.

Tests exercising the entire application through the UI are harder to make repeatable, and have a tendency to be slower and more fragile than unit tests.

把人绕傻吧 2024-10-17 02:48:22

实际上,您可以两者兼得 - 制作一个以用户为中心的驱动程序界面(与 GUI / 技术 / impl 无关)。然后,您可以编写 UIDriver 和 APIDriver 并选择一个驱动程序来运行特定测试。通过 UI 运行通常会比较慢(在进程之外,控件会重新绘制,但以某种方式最初会创建更高级别的置信度)。通过 API 运行速度要快得多(在过程中,轻松设置-拆卸)。

这里的技巧是将“什么”与“如何”分开。否则你最终会遇到 ObscureTests 和高测试维护。确保主要关注测试而不是自动化。

Actually you could do both - make a user-centric Driver interface (agnostic of GUI / tech / impl). You could then write a UIDriver and a APIDriver and choose a driver to run a specific test. Running through the UI is usually slower (out of proc, control repaints but somehow creates a higher level of confidence initially). Running through the API is much faster (in proc, easy setup-teardown).

The trick here is to separate the What from the How. Otherwise you will end up with ObscureTests and high test maintenance. Ensure the primary focus on testing and not automation.

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