许多类在使用配置对象创建(实例化)类时都有快捷名称。快捷名称被称为 别名
(如果类扩展了 Ext.Component,则为 xtype
)。别名/xtype 列在适用类的类名旁边,以便快速参考。
框架类或其成员可以指定为 private
或 protected
。否则,该类/成员为 public
。Public
、protected
和 private
是访问描述符,用于传达类或类成员应如何以及何时使用。
Public 类和类成员可供任何其他类或应用程序代码使用,并且在主要产品版本中可以作为稳定和持久的内容依赖。Public 类和成员可以通过子类安全地扩展。
Protected 类成员是稳定的 public
成员,旨在由拥有类或其子类使用。Protected 成员可以通过子类安全地扩展。
Private 类和类成员由框架内部使用,不供应用程序开发人员使用。Private 类和成员可能会随时更改或从框架中省略,恕不另行通知,并且不应在应用程序逻辑中依赖它们。
static
标签。*请参阅下面的静态。下面是一个示例类成员,我们可以对其进行剖析,以显示类成员的语法(在本例中是从 Ext.button.Button 类查看的 lookupComponent 方法)。
让我们看看成员行的每个部分
lookupComponent
)( item )
)Ext.Component
)。对于不返回除 undefined
以外任何内容的方法,可以省略此项,或者可以显示为以正斜杠 /
分隔的多个可能值,表示返回的内容可能取决于方法调用的结果(即,如果 get 方法调用成功,方法可能返回 Component,如果失败,则返回 false
,这将显示为 Ext.Component/Boolean
)。PROTECTED
- 请参阅下面的标志部分)Ext.container.Container
)。如果成员源自当前类,则源类将显示为蓝色链接,如果它从祖先类或混合类继承,则显示为灰色。查看源代码
)item : Object
)。undefined
以外的值,“返回”部分将注明返回的类或对象类型以及描述(示例中为 Ext.Component
)Available since 3.4.0
- 示例中未显示),紧随成员描述之后Defaults to: false
)API 文档使用许多标志来进一步传达类成员的功能和意图。标签可以用文本标签、缩写或图标表示。
classInstance.method1().method2().etc();
false
,则标记为可阻止的事件将不会触发- 表示框架类
- Singleton 框架类。*有关更多信息,请参阅 singleton 标志
- 组件类型框架类(Ext JS 框架中扩展 Ext.Component 的任何类)
- 表示类、成员或指南在当前查看的版本中是新的
- 表示类型为 config
的类成员
- 表示类型为 property
的类成员
- 表示类型为 method
的类成员
- 表示类型为 event
的类成员
- 表示类型为 theme variable
的类成员
- 表示类型为 theme mixin
的类成员
- 表示类、成员或指南在当前查看的版本中是新的
在 API 文档页面上的类名正下方是一行按钮,对应于当前类拥有的成员类型。每个按钮显示按类型划分的成员计数(此计数在应用过滤器时更新)。单击按钮将导航到该成员部分。将鼠标悬停在成员类型按钮上将显示该类型的所有成员的弹出菜单,以便快速导航。
与类配置选项相关的 Getter 和 Setter 方法将显示在 methods 部分以及 API 文档和成员类型菜单的 configs 部分中,就在它们所作用的配置下方。Getter 和 Setter 方法文档将在 config 行中找到,以便于参考。
您的页面历史记录保存在本地存储中,并显示在顶部标题栏正下方(使用可用的实际空间)。默认情况下,显示的唯一搜索结果是与您当前查看的产品/版本匹配的页面。您可以通过单击历史记录栏右侧的 按钮并选择“全部”单选选项来展开显示的内容。这将显示历史记录栏中所有产品/版本的所有最近页面。
在历史记录配置菜单中,您还将看到最近页面访问的列表。结果按“当前产品/版本”和“全部”单选选项过滤。单击 按钮将清除历史记录栏以及本地存储中保存的历史记录。
如果在历史记录配置菜单中选择“全部”,则将启用“在历史记录栏中显示产品详细信息”的复选框选项。选中后,每个历史页面的产品/版本将与历史记录栏中的页面名称一起显示。将光标悬停在历史记录栏中的页面名称上方也会将产品/版本显示为工具提示。
可以使用页面顶部的搜索字段搜索 API 文档和指南。
在 API 文档页面上,还有一个过滤器输入字段,该字段使用过滤器字符串过滤成员行。除了按字符串过滤外,您还可以按访问级别、继承和只读过滤类成员。这可以使用页面顶部的复选框来完成。
API 类导航树底部的复选框过滤类列表以包括或排除私有类。
单击空的搜索字段将显示您最近 10 次搜索,以便快速导航。
每个 API 文档页面(JavaScript 原始类型页面除外)都有一个与该类相关的元数据菜单视图。此元数据视图将具有以下一项或多项
Ext.button.Button
类具有 Ext.Button
的备用类名)。备用类名通常为了向后兼容性而维护。可运行的示例 (Fiddles) 默认在页面上展开。您可以使用代码块左上角的箭头单独折叠和展开示例代码块。您还可以使用页面右上角的切换按钮切换所有示例的折叠状态。切换所有状态将在页面加载之间记住。
类成员默认在页面上折叠。您可以使用成员行左侧的箭头图标或全局使用右上角的展开/折叠所有切换按钮来展开和折叠成员。
在较窄的屏幕或浏览器上查看文档将导致针对较小外形尺寸优化的视图。桌面视图和“移动”视图之间的主要区别在于
可以通过单击 API 文档页面顶部的类名来查看类源代码。可以通过单击成员行右侧的“查看源代码”链接来查看类成员的源代码。
本教程帮助您使用 Sencha WebTestIt 创建您的第一个 UI 测试。您将逐步自动化我们的 Demoshop 示例的各个部分,并且您可以按照本教程创建所有源文件
本教程的资源以 TypeScript、Java 和 Python 提供。
如果您尚未创建新项目,请按照以下说明操作
单击欢迎标签上的 新建项目链接,或转到 文件 > 新建项目。
在创建新项目对话框中,为您的项目指定名称和位置,然后选择您要使用的脚本语言。
单击 保存 后,Sencha WebTestIt 将创建您的项目并设置运行测试所需的组件。
注意
您选择的编程语言定义了为您设置的自动化框架。如果您选择 TypeScript,Sencha WebTestIt 将为您生成 Protractor 环境。如果您选择 Java,则会设置 TestNg 应用程序。如果您选择 Python,Sencha WebTestIt 将生成 unittest 环境。
您可以在 项目 标签中检查新生成的项目的结构。Sencha WebTestIt 自动为您的测试套件和页面对象创建了文件夹。您可以在项目根目录中看到的文件用于配置您的测试和设置运行测试的环境。项目中值得注意的配置文件如下
文件名 | 描述 |
---|---|
.editorconfig |
包含 Sencha WebTestIt 代码编辑器的代码样式设置。 在此处了解有关 editorconfig 设置的更多信息 |
*.endpoints.json |
存储有关将执行您的测试的端点的信息。 单击此处阅读有关端点的更多信息 |
webtestit.json |
包含 Sencha WebTestIt 测试项目的项目特定选项。 此处定义的所有设置都限定于单个项目,而不是全局设置,您可以通过主菜单 文件 > 首选项 > 用户设置 访问全局设置 |
在本教程中,我们将自动化 Demoshop。您可以在 此处 找到它。继续并查看它。
Demoshop 的主页由不同的部分组成
1 带有菜单和搜索字段的页眉区域
2 列出产品的内容区域
Demoshop 包含各种其他页面。在本教程中,搜索产品并将其添加到购物车。让我们创建一些测试用例,然后我们将对其进行自动化
# | 标题 | 描述 |
---|---|---|
1 | 搜索商品 | 假设 Demoshop 已显示 当用户输入“Super”作为搜索项并按 Enter 键时 那么将显示“Super Cool Goo”的详细信息页面 并且产品名称等于“Super Cool Goo” 并且价格等于 €1,500.00 |
2 | 将商品添加到购物车 | 假设显示“Super Cool Goo”的详细信息页面 当用户单击“添加到购物车”按钮时 那么将显示确认消息 并且商品计数器显示 1 并且购物车区域中的小计等于产品的价格 |
提示
测试用例描述使用 Gherkin 语法。 这是一种定义测试用例的简单方法。每个语句都包含以下三个关键字
- GIVEN 描述当前状态,也称为前提条件
- WHEN 描述用户的操作
- THEN 描述这些操作的结果,也称为断言
这些关键字的组合称为场景。您可以使用逻辑运算符(和/或)链接任何块中的多个语句以创建更复杂的场景。
在设计测试用例时,您仅描述应用程序的预期行为。任何与此的偏差都是意外的,因此被视为测试失败。
现在,让我们使用 Sencha WebTestIt 自动化这些测试用例!
要访问测试用例所需的所有元素,您需要为它们创建选择器。选择器被组织到页面对象中。您可以在 此处 阅读有关选择器的更多信息。
由于您还没有任何页面对象文件,因此您需要创建一个
注意
页面对象不仅包含选择器,还包含模拟的用户输入。实际上,强烈建议仅将页面对象操作暴露给各个测试用例。 这被称为页面对象模式,并在此处进行了描述。
单击项目树工具栏内的 新建页面对象文件。Sencha WebTestIt 在项目的 pageobjects
文件夹中创建一个新文件,并提示您命名它。
或者,右键单击 pageobjects
文件夹,并通过上下文菜单创建文件。命名文件,如果您使用 TypeScript,请使用 HeaderPo.ts
,如果您使用 Java,请使用 HeaderPo.java
,如果您使用 Python,则需要使用蛇形命名法(下划线字符,字符之间没有空格),因此页面对象名称应为 header_po.py
。
新创建的文件带有两个默认函数 open
和 getTitle
。页面对象包含您在 Demoshop 的页眉中需要的所有选择器和操作。
参考
为了更好地维护测试,至关重要的是分析您的网站或应用程序的结构,并将其划分为页面对象。您可以在 本指南的第 3 章 中阅读有关页面对象的更多信息
现在,按照以下步骤为详细信息页面创建另一个页面对象
pageobjects
文件夹,然后从上下文菜单中选择 新建 > 页面对象文件。DetailPagePo.ts
,如果您使用 Java,则命名为 DetailPagePo.java
。同样,由于我们在 Python 中使用蛇形命名法,因此将新页面对象命名为 detail_page_po.py
。设置好所有选择器后,您现在可以编写一些自动化框架将要执行的操作。
让我们从搜索我们的 T 恤衫开始。在现实世界中,用户将单击搜索输入并输入搜索词。请记住,测试自动化本质上是模拟用户。这就是为什么您将完全执行相同的操作。
pageobjects
文件夹中选择 HeaderPo
(header_po
) 文件。searchInput
(_search_input
) 拖动到 代码 选项卡中。insertSearchText
(在 Python 中为 insert_search_text
)。生成的方法是一个简单的构造,可以快速入门并节省您必须编写的代码量。
发送文本后,通过单击 ENTER 键开始搜索。为此,Sencha WebTestIt 会自动将 sendKeys
(send_keys
) 参数添加到方法中。您的代码应如下所示
public void insertSearchText(String text) { this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.searchInput)).sendKeys(text, Keys.RETURN); }
def insert_search_text(self, text): self.wait.until(EC.visibility_of_element_located(self._search_input)).send_keys(text) return self
public async insertSearchText(text: string): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.searchInput)), browser.allScriptsTimeout, this.searchInput.toString()); await element(this.searchInput).sendKeys(text, Key.ENTER); return this; }
提示
生成的页面对象操作是从模板创建的。您可以根据您的网站或应用程序的要求自定义模板。阅读有关 本指南第 3 章中的自定义模板的更多信息。
从 HeaderPo
页面对象中的其余元素中,您想要获取文本。重复上述操作,但这次在弹出菜单中使用 获取元素文本 选项并返回文本字符串,或复制下面的源代码来执行此操作。
public String getCartAmount() { return this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.cartAmount)).getText(); } public String getCartCount() { return this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.cartCount)).getText(); }
def get_cart_amount(self): cart_count_count = self.wait.until(EC.visibility_of_element_located(self._cart_count)).text return cart_count_count def get_cart_count(self): cart_count_text = self.wait.until(EC.visibility_of_element_located(self._cart_count)).text return cart_count_text
public async getCartAmount(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.cartAmount)), browser.allScriptsTimeout, this.cartAmount.toString()); return await element(this.cartAmount).getText(); } public async getCartCount(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.cartCount)), browser.allScriptsTimeout, this.cartCount.toString()); return await element(this.cartCount).getText(); }
做得好!现在从项目的 pageobjects
文件夹中选择 DetailPagePo
,并实现以下函数
文件名 | 描述 |
---|---|
getProductName |
返回 productName 元素的文本。 |
getProductPrice |
返回 productPrice 元素的文本。 |
addProductToCart |
单击 addToCartButton 。 |
getConfirmationMessage |
返回 cartConfirmationMessage 元素的文本。 |
在 Python 中,函数名称分别使用蛇形命名法
最终,DetailPagePo
中的方法应如下所示
public String getProductName() { return this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.productName)).getText(); } public String getProductPrice() { return this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.productPrice)).getText(); } public void addProductToCart() { this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.addToCartButton)).click(); } public String getConfirmationMessage() { return this.wait.until(ExpectedConditions.visibilityOfElementLocated(this.cartConfirmationMessage)).getText(); }
def get_product_name(self): product_name_text = self.wait.until(EC.visibility_of_element_located(self._product_name)).text return product_name_text def get_product_price(self): product_price_text = self.wait.until(EC.visibility_of_element_located(self._product_price)).text return product_price_text def add_product_to_cart(self): self.wait.until(EC.visibility_of_element_located(self._add_to_cart_button)).click() return self def get_confirmation_message(self): cart_confirmation_message_text = self.wait.until(EC.visibility_of_element_located(self._cart_confirmation_message)).text return cart_confirmation_message_text
public async getProductName(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.productName)), browser.allScriptsTimeout, this.productName.toString()); return await element(this.productName).getText(); } public async getProductPrice(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.productPrice)), browser.allScriptsTimeout, this.productPrice.toString()); return await element(this.productPrice).getText(); } public async addProductToCart(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.addToCartButton)), browser.allScriptsTimeout, this.addToCartButton.toString()); await element(this.addToCartButton).click(); return this; } public async getConfirmationMessage(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.cartConfirmationMessage)), browser.allScriptsTimeout, this.cartConfirmationMessage.toString()); return await element(this.cartConfirmationMessage).getText(); }
现在您已准备好自动化测试用例。
要创建新的测试文件,请右键单击项目中的 tests
文件夹,然后从上下文菜单中选择 新建 > 测试文件。Sencha WebTestIt 将为您生成一个新类,并等待您命名它。使用 TypeScript 时将文件命名为 Test1.ts
,使用 Java 时命名为 Test1.java
。这次,您不使用 Python 的蛇形命名法。您使用 camelCase 并将测试文件命名为 test1.py
。
注意
实际的测试文件应编排针对您的网站或应用程序执行的操作。最好将操作本身保留在页面对象中,以确保您的测试具有良好的可维护性。
每个测试用例中最重要的部分是块末尾的断言。您可以使用它来验证网站或应用程序的行为是否与您的预期行为匹配,从而定义测试是失败还是通过。对于元素的断言,有各种断言框架可用。
Sencha WebTestIt 根据您选择的脚本语言将断言框架捆绑到您的项目中。如果您选择用 Java 编写测试,则提供 TestNG 框架。如果您使用 TypeScript,则 Protractor 与 Jasmine 一起是默认设置。对于 Python 用户,提供 unittest 环境。但是,您可以切换各个组件。
根据使用的自动化框架和语言,您可以创建如上表中所述的三个测试用例。
@Test public void SearchForItemTestCase() { // 1. Arrange // Create a new Page Object instance by right-clicking and // selecting "Instantiate Page Object" at the bottom HeaderPo header = new HeaderPo(driver); DetailPagePo detail = new DetailPagePo(driver); header.open("https://demoshop.webtestit.com"); // 2. Act // Call an existing action from your initialized Page Object header.insertSearchText("Super"); // 3. Assert // Use TestNG assertions to verify results. // e.g.: // Assert.assertEquals(title, "Test Automation for GUI Testing | Sencha"); Assert.assertEquals(detail.getProductName(), "Super Cool Goo"); Assert.assertEquals(detail.getProductPrice(), "€1,500.00"); } @Test public void AddItemToCartTestCase() { HeaderPo header = new HeaderPo(driver); DetailPagePo detail = new DetailPagePo(driver); detail.open("https://demoshop.webtestit.com/product/super-cool-goo/"); detail.addProductToCart(); Assert.assertTrue(detail.getConfirmationMessage().contains("“Super Cool Goo” has been added to your cart")); Assert.assertEquals(header.getCartCount(), "1 item"); Assert.assertEquals(header.getCartAmount(), "€1,500.00"); }
def test_search_for_item(self): driver = self.get_driver() """ 1. Arrange Create a new Page Object instance by right-clicking into the code editor and selecting "Instantiate Page Object" at the bottom of the context menu """ header = header_po(driver) detail = detail_page_po(driver) header.open("https://demoshop.webtestit.com") """ 2. Act Call an existing action from your Page Object instance """ header.insert_search_text("Super") """ 3. Assert Use unittest assertions to verify results. e.g.: self.assertEqual(title, "Test Automation for GUI Testing | Sencha") """ self.assertEqual(detail.get_product_name(), "Super Cool Goo") self.assertEqual(detail.get_product_price(), "€1,500.00") def test_add_item_to_cart(self): driver = self.get_driver() header = header_po(driver) detail = detail_page_po(driver) detail.open("https://demoshop.webtestit.com/product/super-cool-goo/") detail.add_product_to_cart() self.assertTrue(detail.get_confirmation_message in "“Super Cool Goo” has been added to your cart") self.assertEqual(header.get_cart_count(), "1 item") self.assertEqual(header.get_cart_ammount(), "€1,500.00")
public async getProductName(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.productName)), browser.allScriptsTimeout, this.productName.toString()); return await element(this.productName).getText(); } public async getProductPrice(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.productPrice)), browser.allScriptsTimeout, this.productPrice.toString()); return await element(this.productPrice).getText(); } public async addProductToCart(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.addToCartButton)), browser.allScriptsTimeout, this.addToCartButton.toString()); await element(this.addToCartButton).click(); return this; } public async getConfirmationMessage(): Promise { await browser.wait(ExpectedConditions.visibilityOf(element(this.cartConfirmationMessage)), browser.allScriptsTimeout, this.cartConfirmationMessage.toString()); return await element(this.cartConfirmationMessage).getText(); }
您已准备好自动化测试用例。
最后,是时候验证我们的实验是否有效了。为此,您必须首先创建一个端点。端点是关于测试运行时环境的一组配置。它定义了要使用哪个浏览器或哪个操作系统,以及更多内容。
注意
由于 Selenium WebDriver 的 JsonWireProtocol,运行时环境实际上可以在世界任何地方,因为自动化的命令是通过 HTTP 发送的。
我们将创建一个本地 Chrome 端点并在其上执行我们的测试。
找到 执行 选项卡
单击 + 按钮
在 端点 对话框中,输入以下信息
单击 保存端点
您可以在 本指南的第 4 章 中了解有关端点的更多信息。
如果您按照本教程中的所有步骤操作,则您的测试用例应无错误地执行。Sencha WebTestIt 在您的项目中创建一个新文件夹 reports
。单击其中的 XML 文件将打开 报告 选项卡,向您显示运行结果。
您还学习了
我们为您创建了一些阅读建议