这几天在找测试开发的工作,今天接到一个杭州面试官的电话面试,记录下面试题,都不难
1. selenium中常见的异常类有哪些
-
NoSuchElementException
-
含义:当无法找到指定的元素时抛出此异常。这是在Selenium自动化测试中最常见的异常之一。
-
可能的原因及解决方法:
-
元素定位方式错误:可能是使用的定位器(如
id、name、xpath、css selector等)无法准确找到元素。例如,id可能被动态生成,在后续的测试运行中发生了改变。此时需要检查元素的定位方式,确保其准确性。可以使用浏览器的开发者工具来重新检查元素的属性,找到一个稳定的定位方式。 -
元素尚未加载完成:如果在页面元素还没有完全加载就尝试访问它,也会出现这个异常。解决方法是可以使用
WebDriverWait等待元素出现,例如:
-
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myElement"))
)
# 对元素进行操作
except NoSuchElementException as e:
print("元素未找到:", e)
-
TimeoutException
-
含义:当等待某个条件(如元素出现、元素可点击等)超时后抛出此异常。
-
可能的原因及解决方法:
-
等待时间设置过短:如果页面加载或者元素的加载和操作需要较长时间,而设置的等待时间不够,就会出现超时。可以适当延长等待时间。例如,如果一个页面包含大量的JavaScript脚本和数据加载,可能需要增加
WebDriverWait的时间参数,从默认的几秒增加到十几秒甚至更长,具体取决于页面的实际情况。 -
页面出现问题导致元素无法在预期时间内加载或可用:可能是网络问题、服务器问题或者页面本身的代码错误。需要检查页面的状态,包括网络连接、服务器响应以及页面的JavaScript控制台是否有错误信息。
-
-
ElementNotInteractableException
-
含义:当元素存在于DOM中,但不能进行交互操作(如点击、输入等)时抛出此异常。
-
可能的原因及解决方法:
-
元素被其他元素遮挡:可能存在一个覆盖在目标元素之上的其他元素,导致无法与目标元素进行交互。可以检查页面布局,尝试先操作遮挡元素(如将其隐藏或移开),或者使用
JavaScriptExecutor来直接执行JavaScript代码进行交互。例如,通过JavaScript来模拟点击操作,绕过Selenium的常规点击方法:
-
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
driver = Chrome()
driver.get("https://example.com")
element = driver.find_element(By.ID, "myUninteractableElement")
driver.execute_script("arguments[0].click();", element)
-
元素状态不符合交互要求:例如,一个按钮可能处于禁用状态,无法点击。需要检查元素的状态属性,确保其满足交互条件,如等待按钮变为可用状态后再进行操作。
-
StaleElementReferenceException
-
含义:当对一个元素的引用在页面发生变化后变得无效时抛出此异常。
-
可能的原因及解决方法:
-
页面刷新或部分更新:如果在获取元素引用后,页面进行了刷新或者通过JavaScript动态更新了部分DOM结构,原来的元素引用就会失效。可以重新定位元素,在每次操作之前检查元素是否仍然有效。例如,在一个动态加载内容的页面中,当加载新的数据后,之前找到的元素可能已经不存在,需要再次使用定位器来找到新的元素:
-
try:
element = driver.find_element(By.ID, "myElement")
# 触发页面更新操作
# 重新定位元素
element = driver.find_element(By.ID, "myElement")
except StaleElementReferenceException as e:
print("元素引用失效:", e)
-
InvalidSelectorException
-
含义:当使用的元素定位选择器(如
xpath、css selector)语法错误或者不被支持时抛出此异常。 -
可能的原因及解决方法:
-
定位器语法错误:例如,
xpath表达式书写错误,可能是路径元素名称写错、轴的使用不当或者谓词条件错误。需要仔细检查定位器语法,可以通过在浏览器的开发者工具中验证xpath或css selector表达式来纠正错误。 -
定位器不被当前浏览器或Selenium版本支持:某些较新的
css selector或xpath特性可能在旧版本的浏览器或Selenium中不被支持。需要检查文档,确保使用的定位器在测试环境中是有效的,或者尝试使用其他更通用的定位方式。
-
2. 如何提高自动测试脚本执行效率
-
多线程技术
-
原理:在编程语言中利用多线程的功能,将自动化测试脚本中的多个测试用例或者任务分配到不同的线程中同时执行。每个线程都有自己的执行路径,可以独立运行,这样可以充分利用多核CPU的资源,提高执行效率。
-
示例(以Python为例):
-
使用
threading模块来并行执行测试函数。假设我们有两个简单的测试函数test_function_1和test_function_2。
-
import threading
def test_function_1():
print("执行测试函数1")
# 这里可以是实际的测试操作,如发送HTTP请求、操作数据库等
for _ in range(1000):
print("测试函数1的操作")
def test_function_2():
print("执行测试函数2")
# 这里可以是实际的测试操作,如发送HTTP请求、操作数据库等
for _ in range(1000):
print("测试函数2的操作")
thread_1 = threading.Thread(target=test_function_1)
thread_2 = threading.Thread(target=test_function_2)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
-
在这个例子中,
thread_1和thread_2分别代表两个线程,它们会同时执行test_function_1和test_function_2。start方法用于启动线程,join方法用于等待线程执行完毕,确保主线程在所有子线程完成后再结束。
-
多进程技术
-
原理:与多线程类似,但进程是操作系统资源分配的基本单位,每个进程都有自己独立的内存空间和系统资源。多进程可以更好地利用多核CPU,避免了线程之间共享资源可能导致的一些问题(如线程安全问题),但进程间的通信相对复杂一些。
-
示例(以Python为例):
-
使用
multiprocessing模块来并行执行测试。
import multiprocessing
def test_function_1():
print("执行测试函数1")
# 这里可以是实际的测试操作,如发送HTTP请求、操作数据库等
for _ in range(1000):
print("测试函数1的操作")
def test_function_2():
print("执行测试函数2")
# 这里可以是实际的测试操作,如发送HTTP请求、操作数据库等
for _ in range(1000):
print("测试函数2的操作")
process_1 = multiprocessing.Process(target=test_function_1)
process_2 = multiprocessing.Process(target=test_function_2)
process_1.start()
process_2.start()
process_1.join()
process_2.join()
-
这里
process_1和process_2是两个独立的进程,它们分别执行test_function_1和test_function_2。同样,start方法启动进程,join方法等待进程结束。
-
分布式测试框架
-
原理:将自动化测试任务分发到多个不同的节点(可以是物理机、虚拟机或者容器)上同时进行。这些节点可以是在本地网络或者云端的不同计算资源。分布式测试框架负责管理测试任务的分配、执行结果的收集和汇总等工作。
-
示例(以Selenium Grid为例):
-
搭建环境:
-
Selenium Grid由一个Hub和多个Nodes组成。Hub是控制中心,负责接收测试请求并将其分发给Nodes。Nodes是实际执行测试的浏览器环境。首先需要下载并启动Selenium Grid Hub和Nodes。
-
启动Hub:
java -jar selenium - server - standalone - 3.141.59.jar - role hub(版本号可能需要根据实际情况调整)。 -
启动Node并注册到Hub:
java -jar selenium - server - standalone - 3.141.59.jar - role node - hub http://localhost:4444/grid/register。 -
编写测试脚本:
-
在测试脚本中,需要配置使用Selenium Grid。以Python为例,使用
Remote方式来指定测试浏览器的驱动。
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
def test_with_grid():
hub_url = "http://localhost:4444/wd/hub"
capabilities = DesiredCapabilities.CHROME
driver = webdriver.Remote(command_executor=hub_url, desired_capabilities=capabilities)
try:
driver.get("https://www.example.com")
# 进行测试操作,如查找元素、点击按钮等
finally:
driver.quit()
-
在这个例子中,测试脚本会将测试任务发送到Selenium Grid的Hub,Hub会将任务分配到一个可用的Node上执行,从而实现了测试的分布式执行。
-
测试框架自带的并行执行功能
-
原理:一些先进的测试框架本身提供了并行执行测试用例的功能。这些框架通常会根据测试用例的特性(如相互独立性)自动将测试用例分配到不同的执行单元(可以是线程、进程或者其他分布式资源)中并行执行。
-
示例(以Pytest - xdist为例):
-
安装:首先需要安装
pytest - xdist插件,使用pip install pytest - xdist。 -
使用方法:在命令行中执行测试时,使用
-n参数来指定并行执行的进程数。例如,pytest -n 4会使用4个进程并行执行测试用例。 -
Pytest会自动将测试用例分配到不同的进程中,并且会收集和汇总每个进程的测试结果。这种方式可以方便地在不修改太多测试脚本的基础上实现并行测试,提高测试效率。
3. 说说常用的python库
1. selenium-webdriver
解释:selenium-webdriver是用于Web自动化测试的核心库,它允许你通过代码控制浏览器的操作,模拟用户在浏览器中的各种行为,如打开网页、点击元素、输入文本、获取页面信息等。支持多种主流浏览器,如Chrome、Firefox、Safari等,需要配合相应的浏览器驱动程序使用。
代码示例:
from selenium import webdriver
# 启动Chrome浏览器
driver = webdriver.Chrome()
# 打开网页
driver.get("https://www.example.com")
# 查找页面元素并进行操作
search_box = driver.find_element("id", "search_box")
search_box.send_keys("自动化测试")
search_box.submit()
# 获取页面标题并打印
page_title = driver.title
print(f"页面标题: {page_title}")
# 关闭浏览器
driver.quit()
2. selenium-webdriver-manager
解释:该库用于自动管理浏览器驱动程序。在使用selenium-webdriver时,通常需要手动下载并配置与浏览器版本匹配的驱动程序,而selenium-webdriver-manager可以自动完成这些驱动程序的下载、安装和管理工作,使测试环境的搭建更加便捷。
代码示例:
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get("https://www.example.com")
driver.quit()
3. appium
解释:appium是一个开源的移动自动化测试框架,用于测试原生、混合和移动网页应用。它基于WebDriver协议,允许测试人员使用类似selenium-webdriver的方式来控制iOS和Android设备上的应用程序,模拟用户在移动设备上的各种操作,如点击、滑动、输入文本等。
代码示例(以安卓应用测试为例):
from appium import webdriver
desired_caps = {
"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.example.app",
"appActivity": "com.example.app.MainActivity"
}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
try:
# 查找元素并进行操作
login_button = driver.find_element_by_id("login_button")
login_button.click()
# 获取应用页面的某个文本元素并打印
text_element = driver.find_element_by_id("welcome_text")
print(f"欢迎文本: {text_element.text}")
finally:
driver.quit()
4. requests
解释:requests是一个简单且强大的HTTP库,用于发送各种HTTP请求(如GET、POST、PUT、DELETE等)。在接口自动化测试中广泛应用,它可以方便地模拟客户端向服务器发送请求,并获取服务器返回的响应,以便验证接口的功能、返回值等是否符合预期。
代码示例:
import requests
# 发送GET请求
response = requests.get("https://api.example.com/users")
print(f"GET请求状态码: {response.status_code}")
print(f"返回数据: {response.json()}")
# 发送POST请求
data = {"name": "test_user", "password": "123456"}
response = requests.post("https://api.example.com/users", json=data)
print(f"POST请求状态码: {response.status_code}")
print(f"返回消息: {response.json()['message']}")
5. json
解释:json库是Python内置的用于处理JSON数据的库。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在Web开发和数据传输中经常使用。json库可以将Python对象转换为JSON字符串(序列化),也可以将JSON字符串转换为Python对象(反序列化)。
代码示例:
import json
# 将Python字典转换为JSON字符串
data_dict = {"name": "John", "age": 30}
json_string = json.dumps(data_dict)
print(f"JSON字符串: {json_string}")
# 将JSON字符串转换为Python字典
json_string = '{"name": "Jane", "age": 25}'
data_dict = json.loads(json_string)
print(f"转换后的字典: {data_dict}")
6. logging
解释:logging是Python内置的标准日志记录库。在测试开发中,它用于记录测试执行的过程、遇到的问题、断言结果等信息。通过配置不同的日志级别(如DEBUG、INFO、WARN、ERROR等),可以灵活控制日志输出的详细程度,有助于调试测试脚本、分析测试失败原因以及生成测试报告。
代码示例:
import logging
# 配置日志记录器
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
def test_function():
logging.info("开始测试函数")
try:
result = 1 / 0
except ZeroDivisionError as e:
logging.error("测试过程中出现错误: %s", e)
test_function()
7. pytest
解释:pytest是一个功能强大且灵活的测试框架,相较于传统的unittest更加简洁和易于使用。它支持自动发现测试用例、丰富的插件生态系统(可实现并行测试、测试覆盖率分析等扩展功能)、参数化测试(方便对测试用例进行参数化,减少代码重复)等特性,广泛应用于各种类型的测试。
代码示例:
def test_addition():
assert 1 + 1 == 2
def test_subtraction():
assert 3 - 1 == 2
if __name__ == '__main__':
pytest.main()
在命令行中运行pytest,它会自动发现并执行以test_开头的测试函数。
8. unittest
解释:unittest是Python内置的标准测试框架。它提供了一套用于编写和运行单元测试的工具,包括通过继承unittest.TestCase类来定义测试用例、编写以test_开头的测试方法、组织测试套件、执行测试以及生成结果报告等功能。
代码示例:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual("hello".upper(), "HELLO")
if __name__ == '__main__':
unittest.main()
9. assertpy
解释:assertpy是一个专门用于编写更具可读性和表现力的断言语句的库。它提供了一系列的断言方法,如assert_that、is_equal_to、is_greater_than等,使得测试代码中的断言部分更加清晰易懂,并且能提供更好的错误信息反馈,有助于快速定位测试失败的原因。
代码示例:
from assertpy import assert_that
def test_string_length():
string = "test"
assert_that(len(string)).is_equal_to(4)
10. pymysql
解释:pymysql用于在Python中连接和操作MySQL数据库。在测试数据库应用程序时,可借助它执行SQL查询、插入、更新和删除操作,从而验证数据库的功能是否正确,比如测试数据库存储过程、验证数据的插入和查询结果是否符合预期等。
代码示例:
import pymysql
# 连接数据库
connection = pymysql.connect(host='localhost',
user='root',
password='password',
database='test_database')
try:
with connection.cursor() as cursor:
# 执行SQL查询
sql = "SELECT * FROM users WHERE age > 20"
cursor.execute(sql)
results = cursor.fetchall()
for row in results:
print(row)
except Exception as e:
print("数据库操作出错:", e)
finally:
connection.close()
11. pyredis
解释:pyredis是用于在Python中与Redis数据库进行交互的库。Redis是一个高性能的键值对存储数据库,常用于缓存、消息队列、计数器等场景。pyredis可以实现对Redis的各种操作,如设置键值对、获取值、删除键、执行列表操作等,在测试涉及Redis的应用程序功能时非常有用。
代码示例:
import redis
# 连接Redis数据库
r = redis.Redis(host='localhost', port=6379, db=0)
# 设置键值对
r.set('name', 'John')
# 获取值并打印
value = r.get('name')
print(f"获取到的值: {value.decode('utf-8')}")
# 删除键
r.delete('name')
12. configparser
解释:configparser用于读取和写入配置文件,通常是INI格式的配置文件。在自动化测试中,配置文件可用于存储测试环境相关的信息,如数据库连接参数、API端点地址、测试账号密码等。通过使用configparser,能方便地在测试脚本中读取这些配置信息,使测试脚本更灵活,易于在不同环境下运行。
代码示例:
import configparser
config = configparser.ConfigParser()
config.read('test_config.ini')
database_host = config.get('database', 'host')
api_endpoint = config.get('api', 'endpoint')
print(database_host, api_endpoint)
13. os
解释:os是Python内置的提供与操作系统交互功能的库。在测试开发中有诸多用途,比如进行文件和目录操作(创建、删除测试数据文件或目录)、获取环境变量(读取与测试环境相关的变量,如测试数据路径、浏览器驱动路径等)以及执行系统命令(在某些特殊测试场景下,可能需要执行外部命令来完成测试,如启动和停止测试服务器)。
代码示例:
import os
# 创建目录
test_dir = 'test_data'
if not os.path.exists(test_dir):
os.makedirs(test_dir)
# 创建文件
file_path = os.path.join(test_dir, 'test_file.txt')
with open(file_path, 'w') as f:
f.write("测试数据")
# 获取环境变量
browser_driver_path = os.getenv('BROWSER_DRIVER_PATH')
print(browser_driver_path)
# 执行系统命令
os.system('ls -l')
14. re
解释:re是Python内置的用于处理正则表达式的库。正则表达式是一种强大的文本模式匹配工具,可用于在文本中查找、替换、分割特定模式的字符串。在测试开发中,常用于验证输入文本是否符合特定格式要求、从网页或其他文本源中提取特定信息等场景。
代码示例:
import re
# 验证邮箱格式
email_pattern = re.compile(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
email = "test@example.com"
if re.match(email_pattern, email):
print(f"{email} 是有效的邮箱地址")
else:
print(f"{email} 不是有效的邮箱地址")
# 从文本中提取数字
text = "There are 10 apples and 5 oranges"
numbers = re.findall(r'\d+', text)
print(f"提取到的数字: {numbers}")
15. pathlib
解释:pathlib是Python内置的用于处理文件路径的库,它提供了一种面向对象的方式来操作文件路径,相比于传统的使用字符串拼接的方式更加简洁、安全且易于理解。可以用于创建、拼接、遍历、判断文件或目录是否存在等操作,在测试涉及文件处理的场景中很有用。
代码示例:
from pathlib import Path
# 创建文件路径对象
file_path = Path('test_data') / 'test_file.txt'
# 判断文件是否存在
if file_path.exists():
print(f"{file_path} 存在")
else:
print(f"{file_path} 不存在")
# 创建目录(如果不存在)
directory_path = Path('new_directory')
directory_path.mkdir(exist_ok=True)
# 遍历目录下的文件
for child in directory_path.iterdir():
print(child)
16. read
你这里提到的“read”应该不是一个完整的库名哦,Python中有很多与读取相关的操作可以通过不同的库或方法来实现,比如open函数用于读取文件内容等。如果你能明确一下具体所指,我可以给出更准确的解释和示例呢。
17. jenkinapi
解释:jenkinapi(假设是指Python的jenkins库)用于与Jenkins服务器进行交互。如果使用Jenkins作为CI/CD工具,通过这个库可以触发构建、获取构建状态和结果、管理作业配置等。在自动化测试完成后,可借助它触发后续的部署作业等操作,实现测试与部署流程的自动化衔接。
代码示例:
import jenkins
server = jenkins.Jenkins('http://localhost:8080/jenkins',
username='admin',
password='password')
job_name = 'test_job'
server.build_job(job_name)
# 获取构建状态
build_info = server.get_build_info(job_name, 1)
print(f"构建状态: {build_info['result']}")
18. locust
解释:locust是一个用于对系统进行性能测试的开源工具,采用Python编写。它可以模拟大量用户对Web应用程序或其他网络服务进行负载测试,通过编写Python脚本定义用户行为,能够方便地测试系统在不同负载情况下的性能指标,如响应时间、吞吐量等。
代码示例:
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
wait_time = between(1, 2.5)
@task
def index_page(self):
self.client.get("/")
运行locust时,可通过其提供的Web界面配置模拟用户数量、孵化率等参数,然后开始性能测试。
19. pillow
解释:pillow是Python Imaging Library(PIL)的一个分支,用于处理图像文件。在测试中,若涉及图像的生成、编辑、验证等功能,可使用pillow。比如测试一个图像裁剪工具,可利用它读取图像,进行裁剪操作后,再验证裁剪后的图像尺寸和内容是否符合预期。
代码示例:
from PIL import Image
def test_image_crop():
# 打开原始图像
original_image = Image.open("original_image.jpg")
width, height = original_image.size
# 模拟裁剪操作(这里裁剪一半宽度)
cropped_image = original_image.crop((0, 0, width // 2, height))
assert cropped_image.size == (width // 2, height)
20. numpy
解释:numpy主要用于处理大型多维数组和矩阵。在测试开发中,当涉及大量数据计算的功能进行测试时,可使用numpy来创建测试数据、进行数据转换和验证。它提供了高效的数学函数和操作,能方便地比较数组内容等操作,用于验证数据处理的准确性。
代码示例:
import numpy as np
def test_array_sum():
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
result = a + b
expected_result = np.array([5, 7, 9])
assert np.array_equal(result, expected_result)
21. matplotlib
解释:matplotlib是一个用于绘制图表和可视化数据的库。在测试开发中,当需要对测试结果进行可视化展示时,比如展示性能测试数据的趋势图、数据分布图表等,可以使用matplotlib来绘制各种类型的图表,使测试结果更直观易懂。
代码示例:
import matplotlib.pyplot as plt
import numpy as np
# 生成一些示例数据
x = np.arange(0, 10)
y = x ** 2
# 绘制折线图
plt.plot(x, y)
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.title('示例图表')
plt.show()
22. pandas
解释:pandas是一个用于数据处理和分析的库,它提供了高效的数据结构(如DataFrame和Series)和丰富的函数来处理、分析、转换和可视化数据。在测试开发中,可用于处理和分析测试数据,比如对大量的测试结果数据进行整理、统计分析、筛选等操作。
代码示例:
import pandas as pd
# 创建一个简单的DataFrame
data = {'name': ['John', 'Jane', 'Jim'],
'age': [30, 25, 35]}
df = pd.DataFrame(data)
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。




946

被折叠的 条评论
为什么被折叠?



