离线环境Selenium自动化测试部署指南:从依赖打包到CI/CD集成

发布时间:2026/6/18 21:48:43
离线环境Selenium自动化测试部署指南:从依赖打包到CI/CD集成 1. 项目概述为什么我们需要一个离线的Selenium环境在自动化测试的日常工作中Selenium几乎是绕不开的名字。它就像测试工程师手中的瑞士军刀能驱动浏览器完成各种复杂的模拟操作。但不知道你有没有遇到过这样的场景公司出于安全考虑核心的测试服务器完全隔离在内部网络无法访问外网或者你需要在一个客户现场的封闭环境中快速部署一套自动化测试框架。这时候你会发现那些“一键安装”的教程瞬间失灵pip install selenium 这条命令变得苍白无力。这就是我们今天要解决的问题离线部署Selenium。这不仅仅是在一台不能上网的机器上装几个包那么简单它是一套完整的、可复现的环境搭建方案。其核心价值在于环境可控、部署可靠、过程可追溯。对于金融、军工、政府等对网络安全有严格要求的行业或者需要为交付给客户的软件产品配套自动化测试能力的团队来说掌握这套技能至关重要。它意味着你的自动化测试能力不再受网络环境的制约可以像部署一个普通应用一样在任何地方快速拉起一套测试环境。接下来我将以一个典型的场景为例你有一台能上网的Windows开发机我们称之为“打包机”和一台完全离线的、运行CentOS 7的Linux测试服务器我们称之为“目标机”。我们的目标是在目标机上搭建一个包含Python、Selenium WebDriver以及对应浏览器以Chrome为例的完整自动化测试环境。整个过程我们将手把手拆解确保每一步你都能看懂、能操作、能成功。2. 环境搭建的整体思路与物料准备在开始动手之前我们必须先理清思路。离线部署的核心矛盾在于目标机没有网络但安装软件又需要依赖。解决这个矛盾的标准思路是**“依赖打包离线搬运”**。2.1 核心思路拆解我们的部署可以分解为三个层次从下到上依次是系统层依赖主要是浏览器运行所需的共享库比如图形库、字体库等。在CentOS 7上我们通常通过yum管理。语言运行时层即Python环境。我们需要一个干净的Python解释器以及pip包管理工具。应用层即Selenium库、浏览器驱动如ChromeDriver和浏览器本体如Chrome。对应的我们的准备工作也需要针对这三层展开。你需要在有网络的“打包机”上提前下载好所有需要的安装包和依赖包。2.2 物料清单与下载指南请在联网的Windows打包机上准备好以下所有物料。我将详细说明每一项的作用和获取方式。1. Python离线安装包对于CentOS 7我强烈建议使用Python 3.8或3.9版本它们与CentOS 7自带的系统库兼容性较好。避免使用太新的Python 3.11可能会遇到glibc版本不兼容的问题。下载地址前往Python官网https://www.python.org/downloads/source/下载对应版本的源代码压缩包例如Python-3.8.18.tgz。选择“Source release”是为了能在目标机上编译安装兼容性最好。2. Selenium及其依赖的Python Wheel包Wheel是Python的一种二进制包格式离线安装时比源码包更方便因为它可能已经包含了编译好的二进制组件。操作方法在打包机上安装一个与目标机架构通常是x86_64一致的Python环境。然后使用pip download命令。# 假设在打包机的某个空目录下操作 mkdir python_packages cd python_packages pip download selenium urllib3 certifi --platform manylinux2014_x86_64 --python-version 38 --only-binary:all:pip download命令用于下载包但不安装。--platform manylinux2014_x86_64指定Linux平台兼容的二进制格式。--python-version 38指定为Python 3.8。--only-binary:all:强制下载wheel包不下载源码。关键依赖urllib3网络请求、certifiCA证书是Selenium运行时常需的。3. Chrome浏览器及ChromeDriver离线包这是Selenium控制Chrome的核心。Chrome RPM包访问Chrome企业版下载页面https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm直接下载最新的稳定版RPM安装包。ChromeDriver访问ChromeDriver下载页https://chromedriver.chromium.org/下载与上述Chrome版本匹配的Linux版压缩包如chromedriver_linux64.zip。版本匹配至关重要不匹配会导致Selenium无法启动浏览器。4. CentOS 7系统依赖包通过Yum离线下载这是最容易出错的一步。我们需要模拟在目标机上安装Chrome和编译Python时可能需要的所有系统库。操作方法在打包机上你可以使用Docker启动一个干净的CentOS 7容器来模拟目标机环境或者如果你有一台临时的、可联网的CentOS 7虚拟机更好。# 在临时的CentOS 7机器上操作 # 1. 安装yum-utils工具它包含yumdownloader命令 sudo yum install -y yum-utils # 2. 创建一个目录存放所有依赖包 mkdir -p /tmp/offline_yum # 3. 下载Chrome可能需要的依赖以实际安装时的报错为准这里是常见集合 sudo yumdownloader --resolve --destdir/tmp/offline_yum \ google-chrome-stable \ alsa-lib \ atk \ cups-libs \ gtk3 \ libXcomposite \ libXcursor \ libXdamage \ libXext \ libXi \ libXrandr \ libXScrnSaver \ libXtst \ pango \ xorg-x11-fonts-100dpi \ xorg-x11-fonts-75dpi \ xorg-x11-fonts-cyrillic \ xorg-x11-fonts-misc \ xorg-x11-fonts-Type1 \ xorg-x11-utils # 4. 下载编译Python 3.8所需的开发工具和库 sudo yumdownloader --resolve --destdir/tmp/offline_yum \ gcc \ make \ zlib-devel \ bzip2-devel \ openssl-devel \ ncurses-devel \ sqlite-devel \ readline-devel \ tk-devel \ libffi-devel \ xz-devel--resolve自动下载依赖的依赖。--destdir指定下载包存放的目录。 操作完成后将/tmp/offline_yum目录下的所有.rpm文件打包。注意不同时期的CentOS 7镜像和Chrome版本所需的依赖可能略有差异。最稳妥的方法是先在目标机或一个干净环境上尝试安装根据报错信息再用yumdownloader下载缺失的包。上述列表是一个覆盖面较广的通用清单。5. 传输工具将所有从打包机上下载好的物料Python源码包、Python wheel包、Chrome RPM、ChromeDriver、Yum依赖包通过U盘、内部文件服务器或任何允许的物理介质拷贝到离线的CentOS 7目标机上。假设我们统一放在目标机的/opt/offline_setup目录下。3. 目标机离线环境部署实操现在我们正式登录到那台离线的CentOS 7服务器。接下来的操作需要root权限或sudo权限。3.1 步骤一部署系统层依赖首先我们需要解决Chrome浏览器和编译Python所需的基础系统库。我们将使用提前下载好的RPM包创建一个本地Yum仓库。# 1. 安装创建本地仓库所需的工具createrepo。由于没网我们需要从CentOS 7安装镜像中获取这个包这里假设你已提前准备好。如果没准备可以跳过创建仓库直接使用rpm -ivh *.rpm强制安装不推荐易出错。 # 假设所有依赖RPM包已在 /opt/offline_setup/yum_packages 目录下 cd /opt/offline_setup/yum_packages # 2. 安装createrepo包如果你有它的rpm文件 sudo rpm -ivh createrepo-*.rpm # 3. 创建本地仓库元数据 sudo createrepo . # 4. 备份原有的Yum源配置并配置使用本地仓库 sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup sudo tee /etc/yum.repos.d/local.repo EOF [local] nameLocal Repository baseurlfile:///opt/offline_setup/yum_packages enabled1 gpgcheck0 EOF # 5. 清理Yum缓存并建立新缓存 sudo yum clean all sudo yum makecache # 6. 安装我们所需的开发工具和库 sudo yum install -y gcc make zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel libffi-devel xz-devel # 7. 安装Chrome的图形依赖库根据之前下载的列表 sudo yum install -y alsa-lib atk cups-libs gtk3 libXcomposite libXcursor libXdamage libXext libXi libXrandr libXScrnSaver libXtst pango xorg-x11-fonts*实操心得第6步安装开发工具时如果本地仓库里包不全yum会报错。这时你需要回到打包机根据错误提示的缺失包名用yumdownloader再次下载补充到yum_packages目录重新运行createrepo .和yum makecache。这个过程可能需要迭代一两次。3.2 步骤二编译安装Python 3.8系统依赖就绪后我们来安装Python。# 1. 切换到存放安装包的目录 cd /opt/offline_setup # 2. 解压Python源码包 tar -xzf Python-3.8.18.tgz cd Python-3.8.18 # 3. 配置编译选项。--prefix指定安装路径这里安装到/usr/local/python38避免影响系统自带的Python2。 sudo ./configure --prefix/usr/local/python38 --enable-optimizations --with-ssl-defaults # --enable-optimizations 会进行一些优化但会使编译时间变长。离线环境时间充裕建议开启。 # --with-ssl-defaults 确保SSL模块正确配置。 # 4. 编译并安装。这个过程视服务器性能可能需要10-30分钟。 sudo make -j $(nproc) # 使用多核编译加速 sudo make altinstall # 使用altinstall而不是install防止替换系统默认的python命令 # 5. 创建软链接方便使用 sudo ln -sf /usr/local/python38/bin/python3.8 /usr/local/bin/python3 sudo ln -sf /usr/local/python38/bin/pip3.8 /usr/local/bin/pip3 # 6. 验证安装 python3 --version pip3 --version重要提示使用make altinstall是关键。它不会覆盖/usr/bin/python这个链接而系统很多工具如yum依赖于Python 2.7。直接make install可能会导致系统管理工具崩溃。3.3 步骤三离线安装Selenium及其依赖Python环境好了接下来安装Selenium的Python库。# 1. 切换到存放Python wheel包的目录 cd /opt/offline_setup/python_packages # 2. 使用pip3离线安装所有wheel包。注意安装顺序先安装基础依赖如urllib3再安装selenium。 sudo /usr/local/bin/pip3 install *.whl # 3. 验证Selenium是否可导入 python3 -c import selenium; print(selenium.__version__)如果这一步报错提示缺少某个依赖说明打包时漏掉了某个包。你需要回到打包机用pip download补下那个包再传输过来重新安装。3.4 步骤四安装Chrome浏览器现在安装浏览器本体。# 1. 进入Chrome RPM包所在目录 cd /opt/offline_setup # 2. 使用yum localinstall安装它会自动处理本地RPM文件的依赖依赖我们已经提前放到本地仓库了 sudo yum localinstall -y google-chrome-stable_current_x86_64.rpm # 3. 验证安装 google-chrome --version # 或 google-chrome-stable --version3.5 步骤五安装与配置ChromeDriverChromeDriver是Selenium控制Chrome的桥梁。# 1. 解压ChromeDriver cd /opt/offline_setup unzip chromedriver_linux64.zip # 2. 将ChromeDriver移动到系统PATH目录并赋予可执行权限 sudo mv chromedriver /usr/local/bin/ sudo chmod x /usr/local/bin/chromedriver # 3. 验证版本匹配 chromedriver --version google-chrome --version请务必核对两个命令输出的主版本号是否一致例如Chrome 124.0.6367.78 对应 ChromeDriver 124.0.6367.78。如果不一致Selenium将无法启动浏览器。4. 验证与编写第一个离线测试脚本环境部署完毕是时候点火测试了。我们编写一个最简单的脚本来验证整个链路是否通畅。在目标机上创建一个测试文件比如test_offline_selenium.py#!/usr/bin/env python3 离线Selenium环境验证脚本 from selenium import webdriver from selenium.webdriver.chrome.options import Options import time def main(): print(【1/4】开始配置Chrome选项...) # 配置Chrome选项适应无图形界面的服务器环境 chrome_options Options() chrome_options.add_argument(--headless) # 无头模式不显示浏览器窗口 chrome_options.add_argument(--no-sandbox) # 在root用户下运行有时需要此参数 chrome_options.add_argument(--disable-dev-shm-usage) # 解决共享内存问题 chrome_options.add_argument(--disable-gpu) # 禁用GPU在某些环境下更稳定 chrome_options.add_argument(--window-size1920,1080) print(【2/4】正在启动ChromeDriver...) try: # 初始化驱动指定我们安装的Chrome二进制文件位置通常已自动在PATH中 driver webdriver.Chrome(optionschrome_options) except Exception as e: print(f启动ChromeDriver失败错误信息{e}) print(可能原因1. Chrome与ChromeDriver版本不匹配2. 缺少动态库依赖3. 权限问题。) return print(【3/4】浏览器启动成功尝试访问本地页面...) try: # 访问一个本地文件或about:blank来测试 driver.get(data:text/html,h1Hello, Offline Selenium!/h1) time.sleep(2) # 等待2秒观察过程 # 获取页面标题进行断言 page_title driver.title page_source driver.page_source print(f页面标题{page_title}) if Hello, Offline Selenium! in page_source: print(✅ 测试成功Selenium已能离线控制Chrome。) else: print(⚠️ 页面内容加载异常。) except Exception as e: print(f访问页面时发生错误{e}) finally: print(【4/4】关闭浏览器清理资源...) driver.quit() print(验证流程结束。) if __name__ __main__: main()运行这个脚本python3 test_offline_selenium.py如果一切顺利你将在终端看到成功的输出而不会弹出任何浏览器窗口因为是无头模式。这个脚本完成了从Python调用Selenium库到Selenium启动ChromeDriver再到ChromeDriver控制无头Chrome浏览器渲染一个简单页面的完整流程。5. 离线环境下的常见问题与深度排查即便按照上述步骤操作在离线环境中你仍可能遇到一些特有的问题。这里我总结了一份“踩坑实录”和排查指南。5.1 浏览器启动失败版本匹配与依赖地狱问题现象执行脚本时报错提示SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version...或WebDriverException: Message: unknown error: cannot find Chrome binary。排查思路版本匹配复查这是最高频的错误。再次运行chromedriver --version和google-chrome --version确保主版本号完全一致。Chrome的自动更新在离线环境不会发生所以一旦配好就是固定的。Chrome二进制路径在某些自定义安装中可能需要显式指定Chrome路径。from selenium.webdriver.chrome.service import Service chrome_options Options() chrome_options.binary_location /usr/bin/google-chrome-stable # 显式指定路径 service Service(/usr/local/bin/chromedriver) driver webdriver.Chrome(serviceservice, optionschrome_options)动态库缺失这是离线环境第二大坑。即使RPM包安装了某些库的链接可能仍有问题。使用ldd命令检查。ldd /usr/bin/google-chrome-stable | grep not found ldd /usr/local/bin/chromedriver | grep not found如果发现有“not found”的库你需要回到“打包机”找到包含这个库的RPM包。可以使用yum whatprovides */libxxx.so命令在联网的CentOS 7上查询然后通过yumdownloader下载传到目标机用rpm -ivh安装。5.2 无头模式下的隐形问题问题现象脚本在无头模式下运行但页面元素找不到、截图空白或者一些JavaScript行为异常。排查技巧增加隐式等待网络请求在离线环境不是问题但页面渲染的异步操作依然存在。在初始化driver后增加隐式等待是好习惯。driver.implicitly_wait(10) # 最多等待10秒使用显式等待对于关键元素使用WebDriverWait配合expected_conditions是更可靠的做法。截图调试在关键步骤后截图保存下来查看页面状态。driver.save_screenshot(/tmp/debug_step1.png)打印页面源码当元素定位失败时打印当前的driver.page_source看看页面HTML是否如你所想。禁用无头模式测试如果条件允许服务器有图形界面或可通过VNC连接可以先注释掉--headless参数观察浏览器实际运行情况这能排除很多无头模式特有的兼容性问题。5.3 资源管理与稳定性优化离线测试服务器可能同时运行多个测试任务资源管理不好容易导致崩溃。优化建议务必调用driver.quit()在finally块或测试用例teardown中确保调用。quit()会关闭所有窗口并终止WebDriver进程而close()只关闭当前窗口。资源泄露累积会导致内存耗尽。限制并发如果使用pytest或unittest等框架并行运行要根据服务器内存限制并发进程数。一个Chrome实例通常消耗200-500MB内存。使用--disable-dev-shm-usage这个启动参数对于在Docker或小内存环境的Linux服务器上运行Chrome至关重要它让Chrome使用/tmp而不是/dev/shm避免共享内存空间不足。日志收集将ChromeDriver的日志输出到文件便于后期分析。service Service(/usr/local/bin/chromedriver) service.log_path /var/log/chromedriver.log # 需要确保有写入权限 driver webdriver.Chrome(serviceservice, optionschrome_options)5.4 离线环境下的测试数据与资源准备你的自动化测试脚本很可能需要访问测试页面、上传文件或读取配置。在离线环境中这些资源也需要提前准备。解决方案搭建本地测试服务器使用Python的http.server模块或Nginx在目标机上托管一个简单的静态网站作为测试目标。# 创建一个测试页面目录 mkdir -p /opt/test_site echo htmlbodyh1Local Test Site/h1input typefile idupload/body/html /opt/test_site/index.html # 启动一个简单的HTTP服务器后台运行 cd /opt/test_site nohup python3 -m http.server 8080 然后在Selenium脚本中访问http://localhost:8080。文件上传测试将测试用的文件如图片、文档提前放到目标机的固定目录在脚本中使用绝对路径如/opt/test_data/example.jpg进行上传操作。配置管理将数据库连接字符串、账号密码等配置信息从代码中剥离使用本地的配置文件如JSON、YAML或环境变量来管理。6. 从搭建到集成融入离线CI/CD流水线环境搭建成功只是第一步让它在离线开发测试流程中持续发挥作用才是最终目的。这里分享如何将这个离线Selenium环境集成到常见的持续集成流程中。6.1 环境标准化与镜像制作为了避免每次部署都重复上述繁琐步骤最佳实践是制作一个标准化环境镜像。方案一Docker镜像如果目标环境支持Docker这是最优雅的方案。你可以基于一个干净的CentOS 7镜像编写Dockerfile将上述所有安装步骤固化其中。最后将构建好的镜像导出为tar文件分发到离线环境加载即可。# Dockerfile 示例片段 FROM centos:7 # 复制所有离线包到镜像中 COPY offline_packages /tmp/offline_packages # 执行一系列RUN命令完成系统依赖安装、Python编译、Chrome安装等 RUN yum install -y ... cd /tmp/offline_packages tar -xzf ... ... # 设置工作目录和默认命令 WORKDIR /workspace CMD [/bin/bash]在离线服务器上只需docker load selenium_offline.tar和docker run ...一个完整的测试环境就瞬间就绪。方案二系统镜像或虚拟机模板如果你使用的是虚拟机如VMware、KVM可以在完成一台机器的完美配置后将其转换为模板或直接克隆。这是物理机或无法使用Docker的环境下的有效选择。6.2 与离线CI工具集成以Jenkins为例假设你的内网已经部署了Jenkins。节点管理将部署好离线Selenium环境的服务器作为Jenkins的一个“永久性代理节点”。在节点配置中要确保工具路径正确如Python3、ChromeDriver的路径。任务配置在Jenkins任务中指定在该代理节点上运行。在“构建环境”或“构建步骤”中使用Execute shell或Batch command。命令中直接调用Python3运行你的测试脚本集。例如cd /path/to/your/test_suite # 安装项目特定的Python依赖如果你也离线打包了 pip3 install --no-index --find-links/path/to/offline_wheels -r requirements.txt # 运行测试例如使用pytest python3 -m pytest tests/ --htmlreport.html --self-contained-html测试报告使用如pytest-html这样的插件生成静态HTML报告。Jenkins可以配置“Post-build Actions”来发布这个HTML报告这样团队成员就可以直接在Jenkins界面上查看测试结果无需登录服务器。6.3 离线依赖包的持续维护你的项目不可能永远只用固定版本的Selenium和Chrome。如何更新建立内部物料仓库在打包机上定期如每季度执行一次依赖包更新流程。更新Python包pip download -r new_requirements.txt ...更新Chrome RPM和ChromeDriver。根据新的Chrome版本在临时CentOS 7环境上测试安装用yumdownloader补充可能新增的系统依赖。版本管理将/opt/offline_setup目录用版本号命名如offline_setup_v2.0。更新时将新物料包传输到目标机的新目录然后更新部署脚本或Dockerfile中的路径指向新版本。这样可以实现回滚。自动化脚本将整个打包过程脚本化。这样当需要更新时只需在打包机上运行这个脚本就能自动下载所有最新物料并打包极大减少人工操作和出错概率。整个离线部署的过程从最初的物料准备到最终的集成落地确实比在线安装繁琐数倍。但它的价值在于提供了绝对的确定性和可控性。一旦这套流程跑通并固化下来你就可以在任何网络隔离的环境中快速、一致地复制出强大的自动化测试能力。这不仅是技术能力的体现更是工程化思维在约束条件下解决问题的典范。