文档帮助

术语、图标和标签

许多类在使用配置对象创建(实例化)类时都有快捷名称。快捷名称被称为 别名(如果类扩展了 Ext.Component,则为 xtype)。别名/xtype 列在适用类的类名旁边,以便快速参考。

访问级别

框架类或其成员可以指定为 privateprotected。否则,该类/成员为 publicPublicprotectedprivate 是访问描述符,用于传达类或类成员应如何以及何时使用。

成员类型

成员语法

下面是一个示例类成员,我们可以对其进行剖析,以显示类成员的语法(在本例中是从 Ext.button.Button 类查看的 lookupComponent 方法)。

lookupComponent ( item ) : Ext.Component
protected

当原始配置对象添加到此容器时调用,无论是在 items 配置的初始化期间,还是在添加新项目 added 或 {@link #insert inserted} 时。

此方法将传递的对象转换为实例化的子组件。

当需要对子创建应用特殊处理时,可以在子类中覆盖此方法。

参数

item :  Object

要添加的配置对象。

返回
Ext.Component

要添加的组件。

让我们看看成员行的每个部分

成员标志

API 文档使用许多标志来进一步传达类成员的功能和意图。标签可以用文本标签、缩写或图标表示。

类图标

- 表示框架类

- Singleton 框架类。*有关更多信息,请参阅 singleton 标志

- 组件类型框架类(Ext JS 框架中扩展 Ext.Component 的任何类)

- 表示类、成员或指南在当前查看的版本中是新的

成员图标

- 表示类型为 config 的类成员

- 表示类型为 property 的类成员

- 表示类型为 method 的类成员

- 表示类型为 event 的类成员

- 表示类型为 theme variable 的类成员

- 表示类型为 theme mixin 的类成员

- 表示类、成员或指南在当前查看的版本中是新的

类成员快速导航菜单

在 API 文档页面上的类名正下方是一行按钮,对应于当前类拥有的成员类型。每个按钮显示按类型划分的成员计数(此计数在应用过滤器时更新)。单击按钮将导航到该成员部分。将鼠标悬停在成员类型按钮上将显示该类型的所有成员的弹出菜单,以便快速导航。

Getter 和 Setter 方法

与类配置选项相关的 Getter 和 Setter 方法将显示在 methods 部分以及 API 文档和成员类型菜单的 configs 部分中,就在它们所作用的配置下方。Getter 和 Setter 方法文档将在 config 行中找到,以便于参考。

历史记录栏

您的页面历史记录保存在本地存储中,并显示在顶部标题栏正下方(使用可用的实际空间)。默认情况下,显示的唯一搜索结果是与您当前查看的产品/版本匹配的页面。您可以通过单击历史记录栏右侧的 按钮并选择“全部”单选选项来展开显示的内容。这将显示历史记录栏中所有产品/版本的所有最近页面。

在历史记录配置菜单中,您还将看到最近页面访问的列表。结果按“当前产品/版本”和“全部”单选选项过滤。单击 按钮将清除历史记录栏以及本地存储中保存的历史记录。

如果在历史记录配置菜单中选择“全部”,则将启用“在历史记录栏中显示产品详细信息”的复选框选项。选中后,每个历史页面的产品/版本将与历史记录栏中的页面名称一起显示。将光标悬停在历史记录栏中的页面名称上方也会将产品/版本显示为工具提示。

搜索和过滤器

可以使用页面顶部的搜索字段搜索 API 文档和指南。

在 API 文档页面上,还有一个过滤器输入字段,该字段使用过滤器字符串过滤成员行。除了按字符串过滤外,您还可以按访问级别、继承和只读过滤类成员。这可以使用页面顶部的复选框来完成。

API 类导航树底部的复选框过滤类列表以包括或排除私有类。

单击空的搜索字段将显示您最近 10 次搜索,以便快速导航。

API 文档类元数据

每个 API 文档页面(JavaScript 原始类型页面除外)都有一个与该类相关的元数据菜单视图。此元数据视图将具有以下一项或多项

展开和折叠示例和类成员

可运行的示例 (Fiddles) 默认在页面上展开。您可以使用代码块左上角的箭头单独折叠和展开示例代码块。您还可以使用页面右上角的切换按钮切换所有示例的折叠状态。切换所有状态将在页面加载之间记住。

类成员默认在页面上折叠。您可以使用成员行左侧的箭头图标或全局使用右上角的展开/折叠所有切换按钮来展开和折叠成员。

桌面与移动视图

在较窄的屏幕或浏览器上查看文档将导致针对较小外形尺寸优化的视图。桌面视图和“移动”视图之间的主要区别在于

查看类源代码

可以通过单击 API 文档页面顶部的类名来查看类源代码。可以通过单击成员行右侧的“查看源代码”链接来查看类成员的源代码。

WebTestIt


顶部

快速入门:创建您的第一个测试

本教程帮助您使用 Sencha WebTestIt 创建您的第一个 UI 测试。您将逐步自动化我们的 Demoshop 示例的各个部分,并且您可以按照本教程创建所有源文件

本教程的资源以 TypeScript、Java 和 Python 提供。

项目结构

如果您尚未创建新项目,请按照以下说明操作

  1. 单击欢迎标签上的 新建项目链接,或转到 文件 > 新建项目

  2. 创建新项目对话框中,为您的项目指定名称和位置,然后选择您要使用的脚本语言。

  3. 单击 保存 后,Sencha WebTestIt 将创建您的项目并设置运行测试所需的组件。

注意

您选择的编程语言定义了为您设置的自动化框架。如果您选择 TypeScript,Sencha WebTestIt 将为您生成 Protractor 环境。如果您选择 Java,则会设置 TestNg 应用程序。如果您选择 Python,Sencha WebTestIt 将生成 unittest 环境。

您可以在 项目 标签中检查新生成的项目的结构。Sencha WebTestIt 自动为您的测试套件和页面对象创建了文件夹。您可以在项目根目录中看到的文件用于配置您的测试和设置运行测试的环境。项目中值得注意的配置文件如下

文件名 描述
.editorconfig 包含 Sencha WebTestIt 代码编辑器的代码样式设置。 在此处了解有关 editorconfig 设置的更多信息
*.endpoints.json 存储有关将执行您的测试的端点的信息。 单击此处阅读有关端点的更多信息
webtestit.json 包含 Sencha WebTestIt 测试项目的项目特定选项。
此处定义的所有设置都限定于单个项目,而不是全局设置,您可以通过主菜单 文件 > 首选项 > 用户设置 访问全局设置

分析被测站点 (SUT)

在本教程中,我们将自动化 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 自动化这些测试用例!

创建页面对象

要访问测试用例所需的所有元素,您需要为它们创建选择器。选择器被组织到页面对象中。您可以在 此处 阅读有关选择器的更多信息。

由于您还没有任何页面对象文件,因此您需要创建一个

注意

页面对象不仅包含选择器,还包含模拟的用户输入。实际上,强烈建议仅将页面对象操作暴露给各个测试用例。 这被称为页面对象模式,并在此处进行了描述

  1. 单击项目树工具栏内的 新建页面对象文件。Sencha WebTestIt 在项目的 pageobjects 文件夹中创建一个新文件,并提示您命名它。

  2. 或者,右键单击 pageobjects 文件夹,并通过上下文菜单创建文件。命名文件,如果您使用 TypeScript,请使用 HeaderPo.ts,如果您使用 Java,请使用 HeaderPo.java,如果您使用 Python,则需要使用蛇形命名法(下划线字符,字符之间没有空格),因此页面对象名称应为 header_po.py

  3. 新创建的文件带有两个默认函数 opengetTitle。页面对象包含您在 Demoshop 的页眉中需要的所有选择器和操作。

参考

为了更好地维护测试,至关重要的是分析您的网站或应用程序的结构,并将其划分为页面对象。您可以在 本指南的第 3 章 中阅读有关页面对象的更多信息

现在,按照以下步骤为详细信息页面创建另一个页面对象

  1. 右键单击 项目 选项卡中的 pageobjects 文件夹,然后从上下文菜单中选择 新建 > 页面对象文件
  2. 如果您使用 TypeScript,则将新页面对象命名为 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 端点并在其上执行我们的测试。

  1. 找到 执行 选项卡

  2. 单击 + 按钮

  3. 端点 对话框中,输入以下信息

  4. 单击 保存端点

您可以在 本指南的第 4 章 中了解有关端点的更多信息。

恭喜!

如果您按照本教程中的所有步骤操作,则您的测试用例应无错误地执行。Sencha WebTestIt 在您的项目中创建一个新文件夹 reports。单击其中的 XML 文件将打开 报告 选项卡,向您显示运行结果。

您还学习了

  • 如何在 Sencha WebTestIt 中创建页面对象
  • 如何手动创建元素
  • 如何使用拖放快速创建页面对象操作
  • 如何创建端点并执行您的测试

从哪里继续

我们为您创建了一些阅读建议

WebTestIt