Selenium定位元素的方法有哪些?
面试的时候,尽量多,全面的说出自己掌握的Selenium定位元素的方法:
- 按ID定位:通过元素的id属性来定位元素,使用find_element_by_id方法。
- 按Name定位:通过元素的name属性来定位元素,使用find_element_by_name方法。
- 按Class Name定位:通过元素的class属性来定位元素,使用find_element_by_class_name方法。
- 按Xpath定位:使用find_element_by_xpath方法。
- 按CSS Selector定位:通过元素的CSS选择器来定位元素,使用find_element_by_css_selector方法。
- 按元素内容定位:通过元素的文本内容来定位元素,使用find_element_by_link_text或find_element_by_partial_link_text等方法。
Appium定位元素的方法有哪些( Xpath规则需要注意 )?
-
通过 ID 定位
-
使用方法 :使用
driver.find_element_by_id()或者MobileBy.ID。-
例如
loc = (MobileBy.ID, 'com.wm.dmall:id/tv_positive')或者driver.find_element_by_id('com.wm.dmall:id/tv_positive')。
-
-
适用场景 :当目标元素有唯一且明确的 resource-id 时使用,这种方法是首选的定位方式之一,因为 ID 具有唯一性,定位准确且高效。
-
-
通过 class_name 定位
- 使用方法 :使用
driver.find_elements_by_class_name('android.widget.TextView')[1]等。不过由于同一页面可能存在多个相同 class 的元素,所以一般结合下标来指定具体某一个元素。 - 适用场景 :适用于页面中存在多个相同类名的元素,且需要定位到特定位置的元素时,但当下标发生变化时,定位可能会不准确。
- 使用方法 :使用
-
通过 accessibility_id 定位
-
使用方法 :
- 使用
driver.find_element_by_accessibility_id()或者MobileBy.ACCESSIBILITY_ID - 例如,
driver.find_element_by_accessibility_id("accessibility_id值")或loc = (MobileBy.ACCESSIBILITY_ID, 'accessibility_id值')。
- 使用
-
适用场景 :对于支持可访问性的应用,当元素的 content-desc 属性值唯一时,可以使用此方法进行快速稳定的定位。
-
-
通过 android_uiautomator 定位
-
text 文本定位语法 :
-
使用 text 文本定义 :
- 如
loc_text = 'new UiSelector().text("登录/注册")',然后driver.find_element_by_android_uiautomator(loc_text).click()。
- 如
-
uiautomator text 模糊定位 :
- 当文本较长时,可以使用
textContains进行模糊匹配, - 如
loc_text = 'new UiSelector().textContains("登录/注册")',然后driver.find_element_by_android_uiautomator(loc_text).click()。
- 当文本较长时,可以使用
-
textMatches 正则匹配查找 :
- 通过正则表达式进行查找定位,
- 如
loc_text = 'new UiSelector().textMatches("^登录/.*")',然后driver.find_element_by_android_uiautomator(loc_text).click()。
-
textStartsWith 以某个文本开头匹配 :
- 如
loc_text = 'new UiSelector().textStartsWith("登录")',然后driver.find_element_by_android_uiautomator(loc_text).click()。
- 如
-
-
resourceId 定位 :
-
resourceId 定位 :
- 和 appium 封装好的 id 定位类似,只是写法变成了 uiautomator 的写法,如
oc_id = 'new UiSelector().resourceId("com.wm.dmall:id/net_image_view ")',然后driver.find_element_by_android_uiautomator(loc_id).click()。
-
-
className 定位 :页面上的 class 属性一般不唯一,多半用在复数定位时候,比如通过 class 属性定位 “同意” 这个按钮下标就是 1。
-
-
通过 XPath 定位
- 使用方法 :使用
driver.find_element_by_xpath()。例如,driver.find_element_by_xpath('//*ele[@class='android.widget.ImageView']') - Xpath定位兄弟元素如何处理?
- 使用方法 :使用
-
在Appium中,可以使用XPath轴定位来定位兄弟元素。以下是一些可以使用的XPath轴:
- following-sibling:表示当前元素之后的所有兄弟元素。
- following-sibling::*:表示当前元素之后的所有同级元素。
- preceding-sibling:表示当前元素之前的所有兄弟元素。
- preceding-sibling::*:表示当前元素之前的所有同级元素。
-
例如,如果要定位一个元素的下一个兄弟元素(即后继兄弟元素),可以使用以下XPath表达式:
//xpath/for/the/current/element/following-sibling::tagName
- 其中,
tagName是要定位的兄弟元素的标签名称。 - 另外,如果要定位一个元素的上一个兄弟元素(即前驱兄弟元素),可以使用以下XPath表达式:
//xpath/for/the/current/element/preceding-sibling::tagName
- 比如下面: 0-11互为兄弟元素
- 我想通过
android.view.ViewGroup[0]找到android.view.ViewGroup[1]里面的元素如何写? - 写法如下:
- 完整XPATH:
"//android.widget.TextView[@resource-id='com.arashivision.insta360akiko:id/setting_item_title']/../../../../preceding-sibling::android.view.ViewGroup[2]"
说几个你知道的adb常用命令?
面试重点记忆: 装包,卸载包,抓日志,获取手机性能信息如CPU,内存,分辨率,拉/推文件到电脑等.
- adb devices - 显示当前连接的设备列表
- adb install <path_to_apk> - 安装应用程序
- adb uninstall <package_name> - 卸载应用程序
- adb pull <remote_path> <local_path> - 从设备中拉取文件
- adb push <local_path> <remote_path> - 将文件推送到设备中
- adb logcat - 查看设备的日志输出
- adb reboot - 重启设备
- adb shell pm list packages - 列出设备上安装的所有应用程序包名
- adb shell input keyevent <key_code> - 发送按键事件到设备。
IOS自动化工具呢,WDA/Tidevice命令了解嘛?
- IOS自动化WDA教程: t.zsxq.com/eR9MA
tidevice是一个用于管理iOS设备的命令行工具,常用命令包括:
- tidevice list --json:列出连接到计算机的所有iOS设备的信息。
- tidevice install :安装一个iOS应用程序。
- tidevice uninstall :卸载一个iOS应用程序。
- tidevice screenshot :在iOS设备上截图并保存到指定路径。
- tidevice logcat:查看iOS设备的日志信息。
- tidevice crashlog:查看iOS设备的崩溃日志。
- tidevice reboot:重启iOS设备。
- tidevice shutdown:关闭iOS设备。
- tidevice pair:配对iOS设备。
- tidevice mount:挂载iOS设备的文件系统。
Selenium 三种等待
Selenium的三大等待是什么?
- 隐式等待 : 指定一个时间,Selenium将在查找元素时等待一定的时间,如果在指定的时间内找到了元素,则继续执行, 如果超过了指定时间仍未找到元素,则抛出NoSuchElementException异常 。
browser.implicately_wait(秒数)
2. 显式等待: 在查找元素时,根据条件等待一定的时间,等待条件成立后再继续执行,可以指定等待的最长时间和轮询周期。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
#最多等待10秒直到元素出现
#等待时间内没有找到元素超时会抛出TimeoutException
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH,'')))
#还可以等待这个元素不出现
WebDriverWait(browser, 10).until_not(EC.presence_of_element_located((By.XPATH,'')))
#等待时间内找到元素超时会抛出TimeoutException
#二者唯一的区别是until和until_not
-
强制等待:比较稳定 ,线程停止,等待固定时间之后再执行脚本
time.sleep(秒数)
简单描述一下Pytest编写用例的规则:(选择性讲几个自己熟悉知道的即可~)
-
用例文件以test_开头并以.py结尾,如test_example.py。
-
用例函数以test_开头,并且使用驼峰命名规则,如test_login_success。
-
在用例函数中使用断言来验证测试结果,确保代码的正确性。
-
使用@pytest.fixture装饰器定义fixture函数,用来管理用例之间的依赖关系和共享资源。
-
使用@pytest.mark.parametrize装饰器来定义参数化测试用例,提高代码的复用性和可读性。
-
使用@pytest.mark.skip装饰器来跳过某些执行失败的用例,以便于调试和维护。
-
使用@pytest.mark.xfail装饰器来标记预期失败的用例,以便于后续修复和验证。
-
使用@pytest.mark.timeout装饰器来设置用例执行的超时时间,避免测试用例无限执行导致阻塞。
-
使用@pytest.mark.dependency装饰器来定义用例之间的依赖关系,保证用例的执行顺序和正确性。
讲一下pytest常见命令行参数的含义?
| 参数 | 描述 | 示例 |
|---|---|---|
-v , --verbose | 增加测试输出的详细程度,显示每个测试用例的详细信息,包括每个测试用例的执行情况(通过、失败等)以及测试用例的名称。 | pytest -v |
-q , --quiet | 减少测试输出的详细程度,只显示测试用例的执行结果(通过或失败的数量),不显示具体的测试用例名称。 | pytest -q |
-s , --capture=no | 禁用输出捕获,允许测试用例中的打印输出(如 print 语句)直接显示在控制台,而不是被捕获和隐藏。 | pytest -s |
-x , --exitfirst | 一旦遇到第一个失败的测试用例,立即停止测试执行,不再继续执行后续的测试用例。 | pytest -x |
--maxfail=num | 设置允许的最大失败测试用例数量,当失败的测试用例数量达到这个值时,停止测试执行。 | pytest --maxfail=2 |
-k expression | 只运行名称与给定表达式匹配的测试用例,表达式可以是测试用例名称的部分内容,支持模糊匹配。 | pytest -k "test_add" |
-m marker | 只运行带有指定标记的测试用例,标记是使用 @pytest.mark 装饰器添加的。 | pytest -m "slow" |
--lf , --last-failed | 只重新运行上一次失败的测试用例,方便快速定位和修复问题。 | pytest --lf |
--ff , --failed-first | 首先运行上一次失败的测试用例,然后再运行其他测试用例。 | pytest --ff |
--durations=N | 显示执行时间最长的 N 个测试用例,帮助找出执行时间较长的测试用例,以便进行优化。 | pytest --durations=5 |
--html=path | 生成 HTML 格式的测试报告, path 是报告文件的保存路径。 | pytest --html=report.html |
--cov=module_path | 测量指定模块或包的代码覆盖率, module_path 是模块或包的路径。 | pytest --cov=my_module |
-n num | 并行运行测试用例, num 是并行运行的进程数,需要安装 pytest-xdist 插件。 | pytest -n 4 |
--junitxml=path | 生成 JUnit XML 格式的测试报告, path 是报告文件的保存路径,常用于与持续集成工具集成。 | pytest --junitxml=test_report.xml |
这些参数可以根据需要组合使用,以满足不同的测试需求。
例如, pytest -v -s --html=report.html 表示以详细模式运行测试,显示测试用例的输出,并生成 HTML 测试报告。
面试官:大致讲一下你知道的pytest的插件有哪些?
1. pytest-xdist :
- 功能 :支持分布式测试,允许你在多个 CPU 或多个主机上并行运行测试,大大加快测试套件的执行速度,尤其是对于大型测试套件非常有用。
- 安装 :
pip install pytest-xdist
- 使用示例 :
pytest -n 4 # 使用 4 个 CPU 核心运行测试
2. pytest-cov :
- 功能 :用于测量测试代码覆盖率,帮助你确定测试用例覆盖了代码的哪些部分,哪些部分还未被测试。
- 安装 :
pip install pytest-cov
- 使用示例 :命令行增加
pytest --cov=your_module_name # 测量 your_module_name 的代码覆盖率
3. pytest-html :
- 功能 :生成 HTML 测试报告,方便查看测试结果和测试历史,提供直观的测试报告,包括测试用例的执行情况、通过和失败的信息等。
- 安装 :
pip install pytest-html
- 使用示例 :
pytest --html=report.html # 生成名为 report.html 的测试报告
4. pytest-repeat :
- 功能 :可以多次重复执行测试用例,对于需要多次运行相同测试用例的情况很有用,例如测试某些具有随机性的功能时,以确保测试结果的一致性。
- 安装 :
pip install pytest-repeat
- 使用示例 :
pytest --count=3 # 重复每个测试用例 3 次
5. pytest-timeout :
- 功能 :为测试用例设置超时时间,如果测试用例执行时间超过设定的超时时间,会自动终止测试并标记为失败,避免长时间运行的测试用例导致测试流程的阻塞。
- 安装 :
pip install pytest-timeout
- 使用示例 :
pytest --timeout=30 # 设置超时时间为 30 秒
6. pytest-mock :
- 功能 :提供方便的 mock 功能,允许你在测试中模拟对象和函数,便于测试代码的不同部分,而不受外部依赖的影响。
- 安装 :
pip install pytest-mock
- 使用示例 :
def test_something(mocker):
mock_func = mocker.patch('your_module.your_function')
# 调用被测试的代码
# 验证 mock 函数是否被调用
mock_func.assert_called_once()
7. pytest-forked :
- 功能 :使用
fork方式运行测试用例,避免测试用例之间的副作用,每个测试用例在独立的进程中运行,确保测试用例之间的独立性。 - 安装 :
pip install pytest-forked
什么是CI/CD,有了解过嘛?
CI/CD是
持续集成(Continuous Integration)和
持续交付/持续部署(Continuous Delivery/Continuous Deployment)的缩写。
持续集成是指将开发人员对代码的更改频繁地集成到共享存储库中,并通过自动化构建和测试过程来验证代码的正确性。通过持续集成,开发团队可以更早地发现和解决代码集成问题,确保代码质量。
持续交付是指通过自动化的构建、测试和部署流程,将应用程序的代码交付给测试、预发布和生产环境,以便让产品团队、测试团队和客户能够快速获取最新的可部署版本。
持续部署是持续交付的进一步延伸,指在经过一系列自动化测试和验证之后,将代码自动部署到生产环境中,实现从代码提交到生产环境上线的全自动化过程。
通过CI/CD实践,团队可以实现代码构建、测试和部署的自动化,提高软件交付的速度、质量和可靠性,从而更快地响应用户需求、减少错误和故障,以及增强团队的协作和效率。
如何通过Jenkins流水线做CI/CD?
最好购买一台Linux云服务器,这样用来跑我们的Jenkins流水线任务方便(jenkins流水线配置教程如下):
知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具
面试差不多按照下面的话术来说即可,主要能答出Jenkins的作用,工作流程等。
Jenkins流水线是Jenkins提供的一种构建Pipeline的方式,可以通过将多个阶段(stage)组合在一起,实现复杂的CI/CD流程。以下是使用Jenkins流水线实现CI/CD的一般步骤:
-
创建Jenkins Pipeline:在Jenkins中创建一个新的Pipeline项目,并配置Pipeline的代码存放库(如Git、SVN等)和Jenkinsfile。
-
编写Jenkinsfile:Jenkinsfile是Pipeline的代码定义文件,其中包含Pipeline的各个阶段(stage)和具体步骤(step),可以使用Groovy语言编写。
-
定义Pipeline阶段:在Jenkinsfile中定义Pipeline的各个阶段,如代码拉取、编译、单元测试、集成测试、打包、部署等。
-
添加Pipeline步骤:在每个阶段中定义具体的步骤,如执行Shell命令、调用外部工具、触发其他Jenkins任务等。
-
实现自动化测试:在Pipeline中包含自动化测试的阶段,确保每次代码提交后自动执行测试并生成测试报告。
-
集成静态代码分析:在Pipeline中集成代码静态分析工具,如SonarQube,用于检测代码质量和安全漏洞。
-
定义部署阶段:在Pipeline中定义部署到各个环境(如测试、预发布、生产)的阶段,确保代码从提交到部署的自动化流程。
-
集成通知和报警:在Pipeline中集成通知插件,如Email、Slack等,以及报警系统,实现在出现问题时及时通知相关人员。
-
触发Pipeline:通过钩子(webhook)、定时器、手动触发等方式,触发Jenkins Pipeline的执行,实现自动化的CI/CD流程。
-
监控和优化:持续监控Pipeline的执行情况和结果,优化流程和效率,保持CI/CD流水线的稳定和高效运行。
Groovy语法及Jenkins流水线解读
1. 概述
Groovy 是一种基于 JVM(Java 虚拟机)的敏捷开发语言,它结合了 Python、Ruby 和 Smalltalk 的许多强大特性。
Groovy 可以与 Java 代码无缝集成,并且能在 Java 平台上轻松运行,既可以作为脚本语言使用,也可以用于开发大型应用程序。
它在 Jenkins 流水线、Gradle 构建脚本等场景中得到了广泛应用。
- 主要特点
2.1 语法简洁
Groovy 继承了 Java 的语法结构,但在此基础上进行了简化,减少了许多样板代码。
例如,定义类和方法时可以省略一些修饰符和分号。
// Java 定义类和方法
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
// Groovy 定义类和方法
class HelloWorld {
static void main(args) {
println 'Hello, World!'
}
}
2.2 动态类型
Groovy 支持动态类型,这意味着在声明变量时不需要显式指定类型,变量的类型会在运行时自动确定。
def message = "Hello, Groovy!"
println message.class // 输出: class java.lang.String
2.3 闭包支持
闭包是 Groovy 的一个强大特性,它是一段可执行的代码块,可以作为参数传递给方法,也可以作为返回值返回。
闭包可以访问其定义时所在的上下文环境。
def greet = { name -> println "Hello, $name!" }
greet("John") // 输出: Hello, John!
2.4 字符串处理灵活
Groovy 提供了多种字符串表示方式,并且支持字符串插值。
def singleQuoted = 'This is a single-quoted string'
def doubleQuoted = "This is a double-quoted string with variable: ${singleQuoted}"
println doubleQuoted // 输出: This is a double-quoted string with variable: This is a single-quoted string
2.5 与 Java 无缝集成
Groovy 可以直接使用 Java 类和库,并且可以在 Groovy 代码中调用 Java 方法。
反之,Java 代码也可以调用 Groovy 代码。
import java.util.ArrayList
def list = new ArrayList()
list.add("element1")
println list.size() // 输出: 1
3. 基本语法
3.1 变量定义
使用 def 关键字定义动态类型变量,也可以显式指定类型。
def number = 10
int anotherNumber = 20
3.2 类和对象
Groovy 中的类定义与 Java 类似,但可以更简洁。
class Person {
String name
int age
void introduce() {
println "My name is $name and I'm $age years old."
}
}
def person = new Person(name: "Alice", age: 25)
person.introduce() // 输出: My name is Alice and I'm 25 years old.
3.3 方法定义
方法定义可以省略返回类型和访问修饰符。
def add(a, b) {
return a + b
}
def result = add(3, 5)
println result // 输出: 8
3.4 控制结构
Groovy 支持常见的控制结构,如 if-else 、 for 、 while 等。
def num = 10
if (num > 5) {
println "Number is greater than 5"
}
for (i in 1..5) {
println i
}
def count = 0
while (count < 3) {
println count
count++
}
4. 在 Jenkins 流水线中的应用
在 Jenkins 流水线中,Groovy 被用于定义流水线的逻辑和步骤。例如:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building the project...'
}
}
stage('Test') {
steps {
sh 'mvn test' // 执行 Maven 测试命令
}
}
stage('Deploy') {
steps {
sh 'mvn deploy' // 执行 Maven 部署命令
}
}
}
}
在这个例子中,整个 Jenkins 流水线的定义就是一个 Groovy 脚本,通过 pipeline 、 stage 和 steps 等关键字来组织和描述软件交付的各个阶段和操作
这段代码是一个使用 Jenkins 持续集成工具编写的 Pipeline 脚本:
-
pipline:- 定义了整个
Jenkins流程,Pipeline是Jenkins2.x 版本引入的一种基于代码的方式来定义和配置CI/CD流程的语法。 - 它允许用户使用 Groovy 语言编写一系列的步骤,这些步骤将按照特定的顺序执行,从而实现自动化的构建、测试、部署等流程。
- 定义了整个
-
agent any:- 指定了执行
Pipeline的代理,可以是Jenkins集群中的任何一个节点。 - 这里的
any表示可以是任何可用的代理节点。
- 指定了执行
-
stages:- 定义了
Pipeline中的阶段,其中包含了任务的不同步骤。 - 每个阶段都是一个独立的步骤单元,可以包含一个或多个步骤。
- 定义了
-
stage('Hello'):- 创建了一个名为
Hello的阶段。这个阶段将包含后续步骤的执行。
- 创建了一个名为
-
steps:- 列出了
Hello阶段中的具体步骤。在这个阶段中,只有一个步骤:
- 列出了
-
echo 'Hello World':- 在控制台输出
Hello World。这通常用于调试或作为流程中的一个标记。
- 在控制台输出
总结来说,这个 Pipeline 的工作流程如下:
Jenkins选择一个可用的代理来执行Pipeline。- 执行
Hello阶段。 - 在
Hello阶段中,打印Hello World到控制台。
Jenkins流水线常见命令解析,快速入门
JenkinsFile 是定义 Jenkins Pipeline 的文件,它使用 Groovy DSL 编写。
Jenkins Pipeline 是一种持续集成和持续交付(CI/CD)的工具,允许用户以代码的方式定义整个 CI/CD 流程。
- Pipeline 定义:JenkinsFile 必须以 pipeline 块开始和结束,定义了整个 Pipeline 的流程和阶段。
pipeline {
// pipeline 定义和配置
}
2. 阶段(Stage)定义:阶段是 Pipeline 中的一个执行阶段,包含一系列的步骤(Step)。
stage('Build') {
// 阶段相关的步骤
}
3. 步骤(Step)定义:步骤是 Pipeline 的最小执行单位,可以是 Shell 命令、Jenkins 插件、或者其他操作。
steps {
sh 'mvn clean install'
}
4. 环境变量定义:可以在 JenkinsFile 中定义环境变量,供 Pipeline 中的步骤使用。
environment {
JAVA_HOME = '/usr/lib/jvm/java-8-openjdk-amd64'
}
5. 条件判断:可以使用 when 来定义条件判断,根据条件执行不同的步骤。
steps {
when {
branch 'master'
}
sh 'echo "This is the master branch"'
}
6. Post 段:可以在 Pipeline 结束后定义一些后续的操作,比如发送通知或者清理资源。
post {
always {
echo 'Pipeline 完成'
}
}