diff --git a/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md b/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md index 0d379b4b4a36..55853e66c0ba 100644 --- a/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md +++ b/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md @@ -4,50 +4,44 @@ linkTitle: "设计策略" weight: 1 --- -{{% pageinfo color="warning" %}} -

- - Most of the documentation found in this section is still in English. - Please note we are not accepting pull requests to translate this content - as translating documentation of legacy components does not add value to - the community nor the project. -

-{{% /pageinfo %}} - -(previously located: https://github.com/SeleniumHQ/selenium/wiki/Bot-Style-Tests) - -## Overview -Over time, projects tend to accumulate large numbers of tests. As the total number of tests increases, -it becomes harder to make changes to the codebase --- a single "simple" change may -cause numerous tests to fail, even though the application still works properly. -Sometimes these problems are unavoidable, but when they do occur you want to be -up and running again as quickly as possible. The following design patterns and -strategies have been used before with WebDriver to help to make tests easier to write and maintain. They may help you too. - -[DomainDrivenDesign]({{< ref "encouraged/domain_specific_language.md" >}}): Express your tests in the language of the end-user of the app. -[PageObjects]({{< ref "encouraged/page_object_models.md" >}}): A simple abstraction of the UI of your web app. -LoadableComponent: Modeling PageObjects as components. -BotStyleTests: Using a command-based approach to automating tests, rather than the object-based approach that PageObjects encourage - -## Loadable Component - -### What Is It? - -The LoadableComponent is a base class that aims to make writing PageObjects -less painful. It does this by providing a standard way of ensuring that pages -are loaded and providing hooks to make debugging the failure of a page to load -easier. You can use it to help reduce the amount of boilerplate code in your -tests, which in turn make maintaining your tests less tiresome. - -There is currently an implementation in Java that ships as part of Selenium 2, -but the approach used is simple enough to be implemented in any language. - -### Simple Usage - -As an example of a UI that we'd like to model, take a look at -the [new issue](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=I-defect%2Cneeds-triaging&projects=&template=bug-report.yml&title=%5B%F0%9F%90%9B+Bug%5D%3A+) page. -From the point of view of a test author, this offers the service of being -able to file a new issue. A basic Page Object would look like: + +(原位置: https://github.com/SeleniumHQ/selenium/wiki/Bot-Style-Tests) + +## 概览 + +随着时间推移, 项目往往会积累大量测试. +随着测试总数的增加, 对代码库进行改动会变得更困难 —— 即便只是一次“简单”的改动, +也可能导致大量测试失败, 而应用本身仍然能正常工作. +有时这种问题不可避免, 但一旦发生, 你希望能尽快恢复运行. +下面介绍的一些设计模式与策略在 WebDriver 场景下被证明可以简化测试编写与维护, +可能也对你有帮助. + +[领域驱动设计]({{< ref "encouraged/domain_specific_language.md" >}}): 以最终用户的语言来表达测试. + +[页面对象]({{< ref "encouraged/page_object_models.md" >}}): 对 Web 应用 UI 的一种简单抽象. + +LoadableComponent: 把页面对象建模为可加载的组件. + +BotStyleTests: 使用以命令为导向的自动化测试方式, 而不是页面对象更偏向的对象化方法 + + +## Loadable Component + +### 其是什么? + +LoadableComponent 是一个基类, 目标是让编写页面对象更轻松. +它通过提供一套标准机制来确保页面被正确加载, 并提供在页面加载失败时用于调试的钩子. +你可以利用它来减少测试中的样板代码, 从而降低维护测试的工作量. + +目前在 Selenium 中包含了一个 Java 实现, +但该方法足够简单, 可在任何语言中实现. + +### 简单用法 + +举个我们想要建模的 UI 的例子, 看看 [new issue](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=I-defect%2Cneeds-triaging&projects=&template=bug-report.yml&title=%5B%F0%9F%90%9B+Bug%5D%3A+) 页面. +对于测试作者而言, 该页面的作用是提供一个提交新 issue 的功能. +一个基本的页面对象看起来像: + ```java package com.example.webdriver; @@ -121,7 +115,8 @@ public class EditIssue { } ``` -In order to turn this into a LoadableComponent, all we need to do is to set that as the base type: +为了把它变成一个 LoadableComponent, +我们所要做的就是将其设为基类: ```java public class EditIssue extends LoadableComponent { @@ -129,10 +124,11 @@ public class EditIssue extends LoadableComponent { } ``` -This signature looks a little unusual, but it all means is that -this class represents a LoadableComponent that loads the EditIssue page. +这个签名看起来有些不寻常, 但它的含义很简单: +该类表示一个用于加载 EditIssue 页面 的 LoadableComponent. -By extending this base class, we need to implement two new methods: + +通过继承这个基类, 我们需要实现两个新方法: ```java @Override @@ -147,15 +143,16 @@ By extending this base class, we need to implement two new methods: } ``` -The `load` method is used to navigate to the page, whilst the `isLoaded` method -is used to determine whether we are on the right page. Although the -method looks like it should return a boolean, instead it performs a -series of assertions using JUnit's Assert class. There can be as -few or as many assertions as you like. By using these assertions -it's possible to give users of the class clear information that -can be used to debug tests. -With a little rework, our PageObject looks like: +`load` 方法用于导航到页面, +而 `isLoaded` 方法用于判断我们是否位于正确的页面. +虽然该方法看起来像是应该返回 boolean, +但实际上它通过 JUnit 的 Assert 类执行一系列断言. +断言可以多也可以少. 通过这些断言, +可以为类的使用者提供清晰的调试信息, +用于定位测试失败的原因. + +稍作改造后, 我们的页面对象如下: ```java package com.example.webdriver; @@ -243,27 +240,25 @@ public class EditIssue extends LoadableComponent { field.sendKeys(text); } } - ``` -That doesn't seem to have bought us much, right? One thing it has done -is encapsulate the information about how to navigate to the page into -the page itself, meaning that this information's not scattered through -the code base. It also means that we can do this in our tests: +看起来似乎没带来太多好处, 对吧? +不过它确实把如何导航到该页面的信息封装进了页面本身, +这意味着这些信息不会散落在代码库各处. +这也意味着我们可以在测试中这样做: ```java EditIssue page = new EditIssue(driver).get(); ``` -This call will cause the driver to navigate to the page if that's necessary. +上述调用会在必要时促使 driver 导航到该页面. -### Nested Components +### 嵌套组件 -LoadableComponents start to become more useful when they are used in -conjunction with other LoadableComponents. Using our example, we could -view the "edit issue" page as a component within a project's website -(after all, we access it via a tab on that site). You also need to be -logged in to file an issue. We could model this as a tree of nested components: +当 LoadableComponent 与其他 LoadableComponent 配合使用时, +会更加有用. 以我们的例子为例, +我们可以把“编辑 issue”页面视为项目网站中的一个组件(毕竟我们是通过该网站的某个选项卡访问它). +并且提交 issue 需要登录. 我们可以把它建模为一棵嵌套组件树: ``` + ProjectPage @@ -271,9 +266,10 @@ logged in to file an issue. We could model this as a tree of nested components: +---+ EditIssue ``` -What would this look like in code? For a start, each logical component -would have its own class. The "load" method in each of them would "get" -the parent. The end result, in addition to the EditIssue class above is: +这在代码中会是什么样子? +首先, 每个逻辑组件都有自己的类. +每个类的 `load` 方法会调用父组件的 `get` 方法. +最终效果, 除了上面的 EditIssue 类外, 还包括: ProjectPage.java: @@ -307,8 +303,8 @@ public class ProjectPage extends LoadableComponent { } } ``` - -and SecuredPage.java: + +以及 SecuredPage.java: ```java package com.example.webdriver; @@ -365,7 +361,7 @@ public class SecuredPage extends LoadableComponent { } ``` -The "load" method in EditIssue now looks like: +EditIssue 中的 `load` 方法现在如下: ```java @Override @@ -376,8 +372,10 @@ The "load" method in EditIssue now looks like: } ``` -This shows that the components are all "nested" within each other. -A call to `get()` in EditIssue will cause all its dependencies to load too. The example usage: + +这表明这些组件都是相互 "嵌套" 的. +在 EditIssue 中调用 `get()` 会导致它的所有依赖组件也被加载. +示例用法: ```java public class FooTest { @@ -409,21 +407,23 @@ public class FooTest { } ``` -If you're using a library such as [Guiceberry](https://github.com/zorzella/guiceberry) in your tests, -the preamble of setting up the PageObjects can be omitted leading to nice, clear, readable tests. +如果在测试中使用像 [Guiceberry](https://github.com/zorzella/guiceberry) 这样的库, +设置页面对象的前置步骤可以省略, 从而使测试更简洁、可读. + +## Bot 模式 -## Bot Pattern -(previously located: https://github.com/SeleniumHQ/selenium/wiki/Bot-Style-Tests) +(原位置: https://github.com/SeleniumHQ/selenium/wiki/Bot-Style-Tests) -Although PageObjects are a useful way of reducing duplication in your tests, -it's not always a pattern that teams feel comfortable following. -An alternative approach is to follow a more "command-like" style of testing. -A "bot" is an action-oriented abstraction over the raw Selenium APIs. -This means that if you find that commands aren't doing the Right Thing -for your app, it's easy to change them. As an example: +尽管页面对象是减少测试重复的一种有效方式, +但并非所有团队都愿意或适应这种模式. +另一种可选的方式是采用更加 "命令式" 的测试风格. + + +“bot” 是对底层 Selenium API 的一种面向动作的抽象. +这意味着如果发现某些命令不适合你的应用, 可以轻松修改它们. 例如: ```java public class ActionBot { @@ -454,15 +454,16 @@ public class ActionBot { } ``` -Once these abstractions have been built and duplication in your tests -identified, it's possible to layer PageObjects on top of bots. + +一旦构建了这些抽象并找出测试中的重复, +就可以在 bot 之上再封装 页面对象. -## Example +## 示例 {{< tabpane text=true >}} {{< tab header="Python" >}} -一个用例 使用 `python + pytest + selenium` 实现了设计策略 "**Action Bot**, **Loadable Component** 和 **Page Object**". +一个用例 使用 `python + pytest + selenium` 实现了设计策略 "**Action Bot**, **Loadable Component** 和 **页面对象**". A `pytest` fixture `chrome_driver`. @@ -486,7 +487,7 @@ A `pytest` fixture `chrome_driver`. {{< /tabpane >}} -"**Action Bot**" implementation. +"**Action Bot**" 实现. {{< tabpane text=true >}} {{< tab header="Python" >}} @@ -510,7 +511,7 @@ A `pytest` fixture `chrome_driver`. {{< /tabpane >}} -"**Loadable Component** definition. +"**Loadable Component** 定义. {{< tabpane text=true >}} {{< tab header="Python" >}} @@ -534,7 +535,7 @@ A `pytest` fixture `chrome_driver`. {{< /tabpane >}} -"**Loadable Component** and **Page Object**" implementation. +"**Loadable Component** 以及 **页面对象**" 实现. {{< tabpane text=true >}} {{< tab header="Python" >}} @@ -557,7 +558,7 @@ A `pytest` fixture `chrome_driver`. {{< /tab >}} {{< /tabpane >}} -Test cases implementation. +测试用例实现. {{< tabpane text=true >}} {{< tab header="Python" >}}