Python +Appium 實(shí)現(xiàn)app自動(dòng)化測(cè)試
一、Appium簡(jiǎn)介
Appium是一款開源工具,用于自動(dòng)化iOS、Android和Windows桌面平臺(tái)上的本地、移動(dòng)web和混合應(yīng)用程序。原生應(yīng)用是指那些使用iOS、Android或Windows sdk編寫的應(yīng)用。移動(dòng)網(wǎng)頁應(yīng)用是通過移動(dòng)瀏覽器訪問的網(wǎng)頁應(yīng)用(appum支持iOS和Chrome上的Safari或Android上的內(nèi)置“瀏覽器”應(yīng)用)?;旌蠎?yīng)用程序有一個(gè)“webview”的包裝,這是一個(gè)允許與web內(nèi)容交互的原生控件。像Apache Cordova這樣的項(xiàng)目可以很容易地使用web技術(shù)構(gòu)建應(yīng)用程序,然后將這些技術(shù)捆綁到原生包裝中,創(chuàng)建一個(gè)混合應(yīng)用程序。
重要的是,Appium是“跨平臺(tái)”的:它允許您使用相同的API在多個(gè)平臺(tái)(iOS、Android、Windows)上編寫測(cè)試。這使得代碼可以在iOS、Android和Windows測(cè)試套件之間重用。
二、環(huán)境所需資源
- JDK
- Android SDK
- Python
- Pycharm
- Appium-Server-GUI
- Appium-Inspector
三、環(huán)境搭建教程
- JDK安裝
- Android SDK配置
- Python安裝
- PyCharm安裝
- Appium安裝
Appium-Server-GUI 配置Android SDK 和 Java JDK 路徑
Appium-Inspector環(huán)境配置
Appium-Inspector運(yùn)行Start Session 界面介紹
四、注意事項(xiàng)
一、Apium-Server-Gui
環(huán)境變量配置:
1. Android SDK安裝目錄;
2. Java JDK安裝目錄;
二、Appium-Inspector
1. 遠(yuǎn)程路徑(Remote Path):/wd/hub
2. 高級(jí)設(shè)置(Advanced Settings):勾選 Allow Unauthorized Certificates,不勾選 Use Proxy
三、手機(jī)設(shè)置進(jìn)入開發(fā)者選項(xiàng)(開發(fā)者模式)
1. 開發(fā)USB調(diào)試
2. 打開USB調(diào)試(安全設(shè)置)
四、手機(jī)安裝AppiumSettings
1. 如果手機(jī)是第一次連接appium,會(huì)提示下載一個(gè)軟件【Appium Settings】,正常下載安裝即可
五、adb 命令
1. adb devices -l 查看已鏈接的設(shè)備
2. adb shell getprop ro.build.version.release 查看Android內(nèi)核版本號(hào)
3. adb shell dumpsys activity | findstr “mResume” 查看手機(jī)屏幕當(dāng)前應(yīng)用頁面Activity名稱已經(jīng)包名 (window)
4. adb shell dumpsys window | grep mCurrent 查看手機(jī)屏幕當(dāng)前應(yīng)用頁面Activity名稱已經(jīng)包名(mac)
六、python代碼
# 新建一個(gè)py文件,例如:mi_8se_testapp.py,將下面代碼復(fù)制粘貼到py文件
import time
from appium import webdriver
# appium 報(bào)錯(cuò) 需要安裝 Appium-Python-Client;webdriver 報(bào)錯(cuò)需要安裝 Appium Python Client: WebDriver module
#安裝方式 在報(bào)錯(cuò)的提示地方點(diǎn)擊 install
from appium.webdriver.common.appiumby import AppiumBy
# For W3C actions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions import interaction
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput
caps = {}
caps["platformName"] = "Android"
caps["appium:platformVersion"] = "10"
caps["appium:deviceName"] = "MI_8_SE"
caps["appium:appPackage"] = "com.app.appnewframe"
caps["appium:appActivity"] = ".activity.LoginActivity"
caps["appium:noReset"] = True
caps["appium:ensureWebviewsHavePages"] = True
caps["appium:nativeWebScreenshot"] = True
caps["appium:newCommandTimeout"] = 3600
caps["appium:connectHardwareKeyboard"] = True
# driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps)
# 或者用下面的配置參數(shù)
desired_caps = {
'platformName': 'Android',
'platformVersion': '10',
'deviceName': 'MI_8_SE',
'appPackage': 'com.test.app',
'appActivity': '.activity.MainActivity',
'noReset': True
}
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
#點(diǎn)擊Remote 查看源碼,其中 command_executor: str = 'http://127.0.0.1:4444/wd/hub'
driver.find_element(by=AppiumBy.ID, value="et_account").set_text("test@admin.com")
driver.find_element(by=AppiumBy.ID, value="et_pwd").set_text("test 123456")
driver.find_element(by=AppiumBy.ID, value="btn_login").click()
# find_element(by=AppiumBy.ID, value="et_account") , 點(diǎn)擊 find_element方法查看源碼,by=AppiumBy.ID,value是元素的 id名稱
# 搜索完后調(diào)用driver.quit()會(huì)直接退出app
# input('**********')
# 10秒鐘之后退出程序
time.sleep(10)
#搜索完后不會(huì)退出app
# driver.quit()
7、TestApp代碼
build.gradle代碼
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.test.app"
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// 簽名文件別名testapp, 123456,123456
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
activity_main.xml布局代碼
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activity.MainActivity">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="30dp"
android:text="Hello World!"
android:textColor="@color/black"
android:textSize="20sp" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_account"
android:layout_width="match_parent"
android:layout_height="46dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="100dp"
android:layout_marginRight="24dp"
android:hint="請(qǐng)輸入手機(jī)號(hào)或者郵箱"
android:textColor="@color/black"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="46dp"
android:layout_margin="24dp"
android:hint="請(qǐng)輸入6 ~ 20 位密碼"
android:maxLength="20"
android:inputType="textPassword"
android:textColor="@color/black"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:background="@color/black"
android:gravity="center"
android:text="登錄"
android:textColor="@color/white"
android:textSize="20sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
MainActivity.kt代碼文章來源:http://www.zghlxwxcb.cn/news/detail-407981.html
package com.test.app.activity
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatEditText
import com.test.app.R
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
private lateinit var et_account: AppCompatEditText
private lateinit var et_pwd: AppCompatEditText
private lateinit var btn_login: AppCompatButton
private val mainScope = MainScope()
private var mToast: Toast? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
initEvent()
}
private fun initView() {
et_account = findViewById(R.id.et_account)
et_pwd = findViewById(R.id.et_pwd)
btn_login = findViewById(R.id.btn_login)
}
private fun initEvent() {
btn_login.setOnClickListener {
login()
}
}
private fun login() {
val account = et_account.text.toString()
if (account.isNullOrBlank()) {
show("請(qǐng)輸入手機(jī)號(hào)或者郵箱")
return
}
val pwd = et_pwd.text.toString()
if (pwd.isNullOrBlank()) {
show("請(qǐng)輸入密碼")
return
}
if (pwd.length < 5) {
show("輸入密碼長(zhǎng)度不能小于5位")
return
}
mainScope.launch {
show("登錄中...")
withContext(Dispatchers.IO) {
//模擬網(wǎng)絡(luò)請(qǐng)求耗時(shí)操作
delay(2000)
}
if ("test@admin.com".equals(account) && "123456".equals(pwd)) {
show("登錄成功")
} else {
show("登錄失敗")
}
}
}
fun show(text: CharSequence?) {
if (TextUtils.isEmpty(text)) return
mToast?.let {
it.cancel()
mToast = null
}
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT)
mToast?.apply {
setText(text)
setGravity(Gravity.CENTER, 0, 0)
show()
}
}
override fun onDestroy() {
mainScope.cancel()
super.onDestroy()
}
}
8、自動(dòng)化測(cè)試效果圖
文章來源地址http://www.zghlxwxcb.cn/news/detail-407981.html
參考文章
- Python+Appium從安裝到第一個(gè)小練習(xí)(保姆級(jí)別教程)
- appium——appium環(huán)境搭建及使用appium進(jìn)行APP測(cè)試
- python+Appium 實(shí)現(xiàn)app自動(dòng)化測(cè)試詳細(xì)講解
到了這里,關(guān)于Python +Appium 實(shí)現(xiàn)app自動(dòng)化測(cè)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!