ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

用 Kotlin 编写 Appium 测试

2021-12-24 10:31:18  阅读:200  来源: 互联网

标签:Appium val Kotlin org caps 编写 import 我们


Kotlin 是一种现代编程语言,专注于简洁、清晰和代码安全。 Google 于 2017 年通过在 Android Studio 中添加支持来正式采用 Kotlin,此后在 Google I/O 2019 上宣布其为 Android 开发人员的首选语言。 也许您的 Android 应用程序团队已将 Kotlin 代码逐步添加到您的项目中或选择开始Kotlin 中的新 Android 项目向前发展。使用相同语言的应用程序代码和 UI 自动化代码有助于工程和 QA 团队在被测试的关键用户旅程上设置水平。我想分享在 Kotlin 中开始编写 Appium 测试的基础知识。我将使用 Google News Android 应用程序作为此示例的目标,并在 HeadSpin 平台上的真实 Google Pixel 3 XL 上进行测试。

Kotlin 与 Java 完全兼容,因此幸运的是,除了在 IntelliJ IDE 中编写代码之外,我们还可以利用 Appium Java 客户端和 JUnit 库。 IntelliJ 有一个名为 IntelliJ IDEA CE 的免费社区版本,可以从他们的网站或通过您的包管理器下载。

开始

在 IntelliJ IDE 中,导航到文件 > 新建项目。选择 Gradle,然后在 Additional Libraries and Frameworks 下选择 Kotlin/JVM。

 

在左侧的 Project 文件视图中,打开 build.gradle 文件并添加以下依赖项:

testCompile 组:'junit',名称:'junit',版本:'4.13'
编译组:'io.appium',名称:'java-client',版本:'7.3.0'

我们将在 src/test/kotlin 项目目录中添加 Appium 测试。

右键单击 kotlin 子目录并选择 New > Kotlin File/Class。 创建三个新类:

  • ProjectCapabilities
  • TestBase
  • GoogleNewsAndroidTest

 

我们将在这三个类中构建项目以使组织清晰。 ProjectCapabilities 类将返回 Desired Capabilities,TestBase 将是我们测试的基类,用于搭建测试设置和拆卸的脚手架,最后 GoogleNewsAndroidTest 类将从我们的 TestBase 继承,使用 Desired Capabilities,并包含我们的测试逻辑。

1. ProjectCapabilities 类

让我们开始使用 ProjectCapabilities 类。 这个类将有一个方法来返回所需的功能。

import org.openqa.selenium.remote.DesiredCapabilities

class ProjectCapabilities {
   companion object {
       fun AndroidBaseCapabilities(): DesiredCapabilities {
           val caps = DesiredCapabilities()
           caps.setCapability("autoAcceptAlerts", true)
           caps.setCapability("platformName", "Android")
           caps.setCapability("automationName", "UiAutomator2")
           caps.setCapability("deviceName", "8ABY0H6YG")
           caps.setCapability("udid", "8ABY0H6YG")
           caps.setCapability("appPackage", "com.google.android.apps.magazines")
           caps.setCapability("appActivity", "com.google.apps.dots.android.app.activity.CurrentsStartActivity")
           return caps
       }
   }
}

Kotlin 中的函数和方法是用“fun”关键字声明的。 您还可以使用冒号后跟类型来指示函数返回类型。 我们可以通过在“伴随对象”中声明它来使其成为静态类方法。 您可以使用“val”创建只读变量和可以使用“var”重新分配的变量。

在这种情况下,我的目标是 HeadSpin 平台中的真正 Pixel 3 XL 设备。 在 HeadSpin Web UI 中,您可以通过单击垂直点菜单并选择自动化配置来获取设备的最低所需功能。

对于 appPackage 和 appActivity,我指定了 Google News Android 应用程序的关联值。

2.TestBase 类

接下来,让我们处理我们的 TestBase 类。默认情况下,Kotlin 中的类是隐式 final 的,不能被继承。为了使类可继承,我们将用“open”关键字标记它。在本课程中,我们将为以下各项创建属性变量:驱动程序、功能、HeadSpin API 令牌和 WebDriver URL。我们将为我们的属性提供可见性修饰符,在这种情况下:

受保护:仅在类或子类中可见
私有:仅在类中可见
我们还将我们的 Desired Capabilities 变量标记为“open”,以便它可以从继承自 TestBase 类的 GoogleNewsAndroidTest 类中覆盖。

此外,您可以指示变量是否可以为空。预先声明这一点的能力是 Kotlin 语言的一个重要特性,因为它可以防止我们的代码出现意外的 NullPointerExceptions。在这种情况下,我们可以用“?”表示驱动程序和大写字母可以为空。在类型之后并将它们设置为空。 Kotlin 还通过使用“$”字符来插入变量或使用“${}”来插入表达式来支持字符串插入。我们将使用这个方便的语言功能将我们的 HeadSpin API 令牌传递给我们的 WebDriver URL 字符串。

我们的 TestBase 还将有两个 JUnit 注释:@Before 用于我们的设置函数,@After 用于我们的拆卸以执行驱动程序退出。我们的设置函数将很简单,它将实例化驱动程序对象。在我们的拆卸函数中,我们将检查驱动程序对象是否不为空,如果是,则退出我们的会话。否则我们将抛出异常。 Kotlin 提供了一个方便的运算符来检查带有“?:”的空条件。这被称为 Elvis Operator,因为如果你把头转向一边,问号字符看起来像一缕头发,冒号看起来像眼睛。

 

你现在看到相似之处了吗? 不管怎样,类的源代码可以在下面找到,让我们继续。 

import io.appium.java_client.MobileElement
import io.appium.java_client.android.AndroidDriver
import org.junit.After
import org.junit.Before
import org.openqa.selenium.remote.DesiredCapabilities
import java.lang.Exception
import java.net.URL

open class TestBase {
   protected var driver: AndroidDriver<MobileElement>? = null
   protected open var caps: DesiredCapabilities? = null
   private val headSpinAPIToken: String = "your-api-token-here"
   private val webDriverURL: URL = URL("https://appium-dev.headspin.io/v0/$headSpinAPIToken/wd/hub")


   @Before
   fun setUp() {
       this.driver = AndroidDriver(webDriverURL, caps)
   }

   @After
   fun tearDown() {
       this.driver?.quit() ?: throw Exception("Driver instance was unable to quit.")
   }

}

 

3. GoogleNewsAndroidTest 类

我们的最后一个类 GoogleNewsAndroidTest 将包含我们的测试逻辑。 这里我们有一个用 JUnit Test 注释注释的测试函数。 我们的测试将简单明了,我们将点击“标题”选项卡按钮,然后从新闻文章列表中向下滚动。 由于我们将执行驱动程序操作,因此我们首先需要确保驱动程序不为空。 Kotlin 提供了一种仅当值不为空时才使用“?”执行操作的方法。 (安全调用运算符)与“let”一起使用。

import io.appium.java_client.MobileBy
import org.junit.Test
import org.openqa.selenium.interactions.Interaction
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.support.ui.ExpectedConditions
import org.openqa.selenium.support.ui.WebDriverWait
import java.time.Duration

class GoogleNewsAndroidTest: TestBase() {
   override var caps: DesiredCapabilities? = ProjectCapabilities.AndroidBaseCapabilities()
   private val headlinesTabButton: String = "com.google.android.apps.magazines:id/tab_headlines"

   @Test
   fun headlinesScrollTest() {

       // Set an explicit wait of 10 seconds
       val wait = WebDriverWait(driver?.let { it }, 10)

       // Tap on the Headlines tab button
       wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.id(headlinesTabButton))).click()

       // Scroll Down
       val finger: PointerInput = PointerInput(PointerInput.Kind.TOUCH, "finger")
       val moveToStart: Interaction = finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), 726, 2452)
       val pressDown: Interaction = finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg());
       val moveToEnd: Interaction = finger.createPointerMove(Duration.ofMillis(1000), PointerInput.Origin.viewport(), 726, 660)
       val pressUp: Interaction = finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg())

       val swipe = Sequence(finger, 0)
       swipe.addAction(moveToStart)
       swipe.addAction(pressDown)
       swipe.addAction(moveToEnd)
       swipe.addAction(pressUp)

       driver?.let { it.perform(arrayListOf(swipe)) }

   }
}

结论

我们这里的工作完成了! 我们现在可以执行我们的测试并观察它的运行情况。

恭喜您现在已经体验了在 Kotlin 中编写 Appium 测试的感觉! 如果这篇文章对您的知识有所帮助,请随意点赞或分享。 您可以在此处下载完整的项目源代码。 

 

标签:Appium,val,Kotlin,org,caps,编写,import,我们
来源: https://blog.csdn.net/HeadSpinDante/article/details/122122304

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有