如何为 Android 应用编写第一个自动测试





5.00/5 (3投票s)
如何为 Android 应用编写第一个自动测试
关于这个主题已经有很多论述。有很多关于如何在测试编写中使用 PageObject
模式的详细解释,以及更多内容。但我们的任务是用 Java 为授权屏幕编写我们的第一个简单测试。让我们开始吧,看看如何解决这个问题!
移动应用测试简介
目前,在测试几乎任何移动应用时,您都必须处理两个操作系统:iOS 和 Android。本文将重点介绍如何处理 Android 应用。
要选择一种合适的移动应用测试方法,我们必须清楚所涉及的应用类型。目前,有三种类型的应用:
-
原生应用 - 这些是直接安装并运行在智能手机上的应用。原生应用不需要与浏览器和互联网进行交互;
-
Web 应用 - 这些应用已适配桌面和移动版本;
-
混合应用 - 包含内置 Web 页面打开功能的原生应用。
确定了要使用的移动应用类型后,我们就可以安全地着手开发测试了。测试通常被理解为一系列步骤,一旦完成,即可将产品带到期望的状态。在测试过程中,将执行预先确定的所有测试。
软件质量保证测试通常涉及两种类型:手动和自动化。在手动测试中,测试由测试人员执行;该职位通常被称为手动 QA 工程师。测试人员是测试和应用程序之间的连接。这看起来有点像这样:
说测试人员直接与应用程序一起工作是不准确的。在运行测试时,他们会按下按钮或在字段中输入数据。换句话说,他们与应用程序的界面进行交互。此外,测试人员还会与服务 API、网络接口、CLI、GUI 等进行交互。API 由客户端程序用于与服务器交互,而 GUI 则由人类使用。
手动测试无疑是好的,但让我们看看如何用自动化流程取代人工劳动。应用程序的交互对象将是软件客户端,而不是测试人员。谁来运行测试?当然,正确!测试框架将负责运行测试。它会运行测试、显示结果、存储测试运行历史记录,并执行许多其他功能。
要处理 GUI 界面,我们需要特殊的适配器,也称为驱动程序(是的,是的,你们中的许多人会记得,要在计算机上播放声音,或者,比方说,要确保显卡传输视频显示信号,就需要安装一些驱动程序)。例如,我们的测试包含一个点击“搜索”按钮的步骤。驱动程序接收点击“搜索”按钮的命令,然后将其传递给应用程序中的所需接口。这确保了搜索按钮被按下并且测试成功通过。但是,如果没有要按下的按钮,或者由于某种原因它没有被打包,就会出现错误,测试也会崩溃。
为了解决一些非标准任务,或者需要增加日志级别,驱动程序的功能通常是不够的。这时就需要使用各种包装器来处理这些问题。例如,Kakao 或 Kaspresso。这些包装器可能因任务不同而差异很大。有些只是语法糖(不影响软件行为但使语言更人性化的语法功能)。相反,另一些则涵盖了相对广泛的复杂任务。
安装工具
选择一门语言
有多种语言可用于自动化测试过程,例如 Java、Python、Kotlin、Swift、JavaScript 等等。这完全取决于您的偏好和您追求的目标。在我们的示例中,我们将使用 Java。为此,您需要从官方网站下载并安装它。
Android Studio
Android 应用可以在物理设备或模拟器上运行。通常,自动化测试在模拟器上运行。为此,您需要从官方网站下载并安装 Android Studio。
Appium
我们可以使用的下一个工具是 Appium(一个帮助自动化 Android 和 iOS 应用的开源工具)。Appium 有两种运行方式:UI 或基于控制台。要安装和运行控制台版本,我们还需要 NodeJs。请注意,UI 版本可以从官方网站下载,并且可以立即使用。
Appium Inspector
我们需要一个 GUI Inspector 来查找定位符(定位符是自动化测试 (autotest) 可以用来查找界面中的某个项的路径)。
Appium Inspector 基本上就是一个具有用户界面的 Appium 客户端,它显示正在测试的应用的屏幕,我们可以在其中查看项的路径。
IntelliJ IDEA
我们将在 IntelliJ IDEA 中开发测试,该工具也可以从官方网站下载,我建议您选择社区版。
应用程序
我们将为一款您可以在 Android Studio 中自行下载和构建的应用开发测试。它可以通过此链接获取。或者,您可以下载该应用。
设置和安装 Android Studio 模拟器
为 Android 自动化测试选择操作系统并非特别关键。您可以使用 Windows、Linux 或 MacOS。
要开始测试,我们需要安装 Android SDK 和 Android Studio。我们必须创建一个模拟器。我们将在此处仅简要介绍这一点,因为配置模拟器的指南非常详细,并在官方文档中提供了关键详细信息。
设置 Appium
在设置好 Android Studio 后,就可以设置 Appium 了。打开我们之前安装的 Appium UI。我们在 Host 字段中输入地址 0.0.0.0,在 Port 字段中输入 4723。
接下来,转到“编辑配置”,并指定 ANDROID_HOME 和 JAVA_HOME 路径,如下图所示,然后单击“保存并重新启动”。
请注意,您的路径可能与屏幕截图中的路径不同,至少在用户名称方面会不同。
接下来,转到 Appium 的“高级”选项卡,并确保“服务器地址”和“服务器端口”字段中的设置与下图中的设置相同。
设置完所有必需字段后,单击“启动服务器”按钮,并确保 Appium 服务器正在运行。
我们现在不需要对此做任何事情;让 Appium 服务器保持运行。
设置 Appium Inspector 和定位符搜索
为了让我们的测试理解我们将与之交互的界面项,我们需要知道如何访问这些元素。为此,请运行 Appium Inspector,并指定 Remote Host: 0.0.0.0,以及 Remote Path /wd/hub,如下图所示。
现在让我们来处理 Capability。Capability 是一组用于启动 Appium 会话的参数和值。该集合的信息描述了您在运行模拟器时所需的“功能”,例如特定的移动操作系统或特定版本的设备。Capability 以键值对的形式表示;值可以是任何有效的 JSON 类型。
{
"appium:platformName": "Android,"
"appium:deviceName": "autoschool10",
"appium:app": "/Users/s.yakovlev/Desktop/login.apk"
}
在变量 appium:platformName
中,我们指定 Android 平台;在变量 appium:deviceName
中,我们指定我们创建的 Android 模拟器的名称,在本例中为“autoschool10
”,以及 .apk 文件的路径。
我们将保存指定的 Capability,并将此预设命名为 loginAndroidApp
。名称无关紧要,但它应该对您来说有意义且易于理解。
已保存的 Capability 可以在“已保存的 Capability”选项卡中找到。
现在,我们只需打开 Android Studio,运行我们之前创建的模拟器,然后在 Appium Inspector 中单击“启动会话”。
这将启动 Appium Inspector,在左侧显示屏幕截图,在右侧显示项树。
我们将编写三个测试。
- 第一个将检查登录用户名是否显示在标签栏中。
- 第二个测试将检查有利的授权场景。
- 第三个测试将检查不利的授权场景。
为此,我们需要知道这些项的路径。让我们从标签栏开始。单击登录名称,您将看到该项的属性显示在右侧。
我们将写出该项的 ID,稍后我们将需要它:com.example.login:id/toolbar
。
对“电子邮件”和“密码”字段执行相同的操作。电子邮件字段的 ID 为 com.example.login:id/username
,密码字段的 ID 为 com.example.login:id/password
。
此外,我们还要找出“登录”或“注册”按钮的 ID。
其 ID 为 com.example.login:id/login
。
如果用户输入以下有效电子邮件数据:admin@admin.ru 和密码:1234,则下方将显示文本:“欢迎!用户”。让我们将数据输入字段并进行检查。
但是,您可以看到,Inspector 中没有任何变化,而我们需要找出此文本字段的 ID。没关系;我们只需单击“刷新”按钮。
然后拍摄新截图。我们获得了一个新屏幕截图,现在可以找出此文本字段的 ID com.example.login:id/succestext
。
如果在模拟器中输入了无效的密码或电子邮件,将显示一条授权错误消息以及相应的文本。
您可能已经注意到,此错误消息具有相同的 ID,但如果仔细观察,您会发现文本字段中的错误文本完全不同。这正是我们需要的。
现在我们已经写出了所有项的 ID,让我们开始编写测试。
配置库
我们将在 IntelliJ IDEA 中开发测试。为此,请启动 IDEA,并在桌面上创建一个目录,例如,命名为 androidAutomation。
创建默认项目后,让我们将库连接到它:
为了方便起见,我们已将所有库集中在一起。
打开我们已经创建的项目,并创建一个 libs 目录。
接下来,将下载的库放入我们的目录中。
现在,让我们进入项目,在“项目结构”下,并从 libs 文件夹添加我们的库。
我们已经添加了所有工作所需库,现在必须创建一个目录来存放我们的应用程序。创建 apps 目录并将我们的应用程序拖入其中。
开发测试
现在,我们转到主 Java 目录,并创建我们的第一个类,名为 LoginTest
,我们将在其中编写测试。
要成功运行测试,我们需要 setUp()
、tearDown()
方法和测试本身。让我们编写 setUp()
方法,在该方法中我们将编写所有必需的测试运行参数,具体如下:
platformName
:我们模拟器的操作系统版本,在本例中为 Android;deviceName
:在 Android Studio 中显示的模拟器名称,在本例中为autoschool10
(模拟器名称可以是任何名称,但最好确保它不是用西里尔文写的);platformVersion
:我们的操作系统版本 - Android 10;automationName
:我们使用 Appium 进行自动化;appPackage
:我们的测试应用的包名com.example.login
;appActivity
:启动的活动,即屏幕。我们的应用只有一个屏幕,该活动称为.ui.login.LoginActivity
;app
:这里我们指定应用程序的完整路径,在本例中为“/Users/{user_name}/Desktop/androidAutomation/apks/login.apk.
”
我们使用此行连接 Android 驱动程序(Appium Android Driver 是 Android 设备的测试自动化工具。该驱动程序是 Appium 移动测试自动化工具的一部分)。
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
Android.uiautomator.testrunner.UiAutomatorTestCase
放置在 Android 设备上,并在端口 4723 上打开一个 SocketServer
。该服务器接收命令,将其转换为适当的 Android UI Automator 命令,并在设备上运行它们。
完整的代码列表如下。
public void setUp() throws Exception
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "autoschool10");
capabilities.setCapability("platformVersion", "10");
capabilities.setCapability("automationName", "Appium");
capabilities.setCapability("appPackage", "com.example.login");
capabilities.setCapability("appActivity", ".ui.login.LoginActivity");
capabilities.setCapability("app",
"/Users/s.yakovlev/Desktop/androidAutomation/apks/login.apk");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
我们在 tearDown()
方法中终止驱动程序。
public void tearDown()
{
driver.quit();
}
接下来,让我们添加注解 @before
—在测试之前执行;@After
—在测试之后执行;@Test
—为每个测试添加。
现在我们要做的就是编写测试本身。我们将编写三个测试。第一个将检查登录屏幕是否已打开。第二个测试将检查授权(使用有效数据),第三个逻辑测试将检查批准(使用无效数据)。
标签栏测试
让我们编写一个积极的屏幕标题测试。我们将声明一个名为 screenTitle
的变量,用于保存我们的元素。我们将通过 id
搜索此元素,以编写 findElementById
。为了确保元素(项)确实存在,让我们调用 isDisplayed()
方法。
@Test
public void checkTitleScreen()
{
WebElement screenTitle = driver.findElementById("com.example.login:id/toolbar");
screenTitle.isDisplayed();
}
使用有效数据进行授权测试
让我们继续使用有效数据编写授权测试。步骤顺序将相同。我们设置变量 emailInput
和 passInput
,并在其中保存我们之前找到的元素。
要向字段输入数据,必须先单击它。有一个 click()
方法可以做到这一点,而 sendKeys()
方法将用于输入我们要插入到字段中的传输数据。
@Test
public void validRegistrationTest()
{
WebElement emailInput = driver.findElementById("com.example.login:id/username");
emailInput.isDisplayed();
emailInput.click();
emailInput.sendKeys("admin@admin.ru");
WebElement passInput = driver.findElementById("com.example.login:id/password");
passInput.isDisplayed();
passInput.click();
passInput.sendKeys("1234");
WebElement signInButton = driver.findElementById("com.example.login:id/login");
signInButton.isDisplayed();
signInButton.click();
WebElement successAuthText = driver.findElementByXPath
("//*[contains(@text, 'Welcome ! user')]");
successAuthText.isDisplayed();
}
请注意,我们通过 id
查找项,而对于文本“Welcome ! user
”,我们则使用 XPath 进行搜索。这是查找定位符的第二种选择。XPath 用于导航元素和属性。以下结构 findElementByXPath("//[contains@text, 'Welcome ! user')]");
用于在屏幕上的任何位置搜索文本。contains()
方法不需要所有读者来正确识别项;只需要部分文本即可,但这部分文本必须是唯一的。
使用无效数据进行授权测试
同样,让我们为数据无效的情况编写一个授权测试。
@Test
public void validRegistrationTest()
{
WebElement emailInput = driver.findElementById("com.example.login:id/username");
emailInput.isDisplayed();
emailInput.click();
emailInput.sendKeys("user@user.ru");
WebElement passInput = driver.findElementById("com.example.login:id/password");
passInput.isDisplayed();
passInput.click();
passInput.sendKeys("1111");
WebElement signInButton = driver.findElementById("com.example.login:id/login");
signInButton.isDisplayed();
signInButton.click();
WebElement successAuthText = driver.findElementByXPath
("//*[contains(@text, 'Login failed')]");
successAuthText.isDisplayed();
}
我们的测试现在已经编写完毕,可以运行了。要运行所有测试,请单击 LoginTest
类旁边的绿色三角形。
重要提示:在运行之前,请确保 Appium 服务器 GUI 正在运行,并且模拟器也正在运行。
我们的测试正在运行,我们可以观察模拟器以查看过程如何进行 - 字段正在填充数据;如果测试成功,则会用绿色复选标记标记。
运行完成后,我们可以查看默认报告。它可能不够详尽,但它仍然表明我们的测试是成功的。
结论
因此,我们已经了解了如何为 Android 移动应用编写 Java 测试。当然,这些测试远非完美。项目通常涉及编写整个框架并使用 PageObject
模式。但我们的任务是编写第一个测试,您可以在不使用 PageObject
模式的情况下开始。
历史
- 2023 年 4 月 12 日:初始版本