Harbor自动化测试 | 少走三年弯路
▌ 技术引导 Harbor自动化测试绕不开的几个坑,我踩过一次就记一辈子。配置环境的时候,千万别用默认的Docker网络,除非你真的不怕连不上。我试过用host网络,结果反而导致测试容器和宿主机的端口冲突,挂掉两次。还有,测试用例写得再好,不加--no-color参数,调试时信息全乱,根本看不清到底是容器报错还是脚本问题。最恶心的是,有些测试环境变量写死在代码里,根本没法动态改,跑测试时还要手动改配置,效率低得要命。用Jenkins做CI的话,千万别把测试脚本和构建脚本混在一起,分开执行能省不少麻烦。另外,别用curl发请求,用JUnit5+RestAssured能直接拿到响应体和日志,调试起来顺手得多。 测试脚本运行前先执行docker-compose down,再docker-compose up --build,别省略这个步骤,不然旧镜像残留会让测试数据混乱。Harbor API文档写得不清楚,测试的时候多加--insecure参数,不然https握手会出问题。我之前用Postman测试API,结果因为没有加Authorization头,每次请求都提示401。后来才发现,Harbor的API认证是基于Bearer Token,得用curl -H "Authorization: Bearer "这种方式。测试数据清理也得重视,比如用docker rm -f或者docker system prune,别懒,不然测试结果不准。 测试阶段一定要用harbor的测试账号,别用管理员,权限太大容易暴露真实数据。测试脚本里加日志也别偷懒,用LOG.info("Test step: ...")能帮你快速定位问题。一不小心用错了API路径,比如把/v2/_catalog写成/v2/catalog,结果全测不通过。Harbor的版本差异也得注意,比如v2.0和v2.5在API上有些细微区别,用curl测试的时候容易出错。别用万能的assert,得写具体,比如assertThat(response.body().as(String.class), containsString("error")),这样更精准。 测试时用docker run启动容器时,别忘记加--rm参数,否则容器不会自动删,占空间。写测试用例的时候,记得用@DisplayName注解给每个测试方法起个好名字,不然看结果时连自己写了啥都记不清。Harbor的测试脚本要用指定的base镜像,比如harbor:latest,否则兼容性出问题。测试脚本执行前,最好先运行一次手动测试,确认预期结果,再写自动化脚本,不然会浪费大量时间在无意义的失败上。 Harbor自动化测试最怕的就是环境变量没配对,比如HARBOR_URL写错,或者数据库密码没改。脚本执行前得检查所有变量,否则连登录都失败。测试数据得用临时数据库,别用正式的,不然数据污染风险太大。测试用的用户要单独建,权限控制到最小,防止误操作影响真实数据。脚本执行的时候,别用多线程,单线程更稳定,容易复现问题。测试报告得用JUnit的XML格式,方便集成到CI系统里。 ▌ 技术参考 Harbor自动化测试的核心在于构建稳定的测试环境,同时避免因配置错误导致的失败。Harbor本身设计为私有镜像仓库,支持API调用,但其API文档并没有像Docker Hub那样详细,很多参数需要自行探索或者参考社区的实践。例如,获取仓库列表的API路径是 /v2/_catalog,返回的数据是JSON格式,包含name字段。测试时务必确认版本兼容性,比如在Harbor v2.5中,这个路径依然有效,但在某些旧版本中可能被废弃。 测试脚本编写时,推荐使用JUnit5框架配合RestAssured组件,这样能更高效地处理HTTP请求。例如,使用RestAssured.get("/v2/_catalog")来获取仓库列表,同时添加@DisplayName注解让测试报告更清晰。测试时记得加上--insecure参数,避免SSL证书验证失败。例如:curl -k -X GET "https:///v2/_catalog" -H "Authorization: Bearer "。这种方法可以绕过证书检查,适合测试环境。 测试环境搭建时,务必使用docker-compose来管理容器,而不是直接运行docker run命令。例如,在docker-compose.yml中配置一个harbor服务,指定环境变量如HARBOR_INSECURE_REGISTRY: "true",这样能避免HTTPS握手问题。另外,使用--rm参数让容器在测试结束后自动删除,防止数据残留。写测试用例前,先手动执行一次,确认预期行为,再编写自动化脚本,这样能节省大量调试时间。 测试数据管理是自动化测试的关键环节。Harbor的测试环境应当使用独立的数据库,避免和生产环境数据混淆。例如,在docker-compose.yml中,可以配置一个MySQL服务,并通过环境变量指定数据目录为/tmp/mysql_data,这样每次测试都能重置数据。测试脚本执行前,先调用docker rm -f命令删除残留容器,再运行docker-compose up --build来重新构建测试环境。这种方式能确保测试的稳定性,避免因旧镜像导致的错误。 自动化测试脚本中,权限控制是不可忽视的一点。测试账号应使用Harbor的测试用户,而不是管理员账号。例如,在Harbor UI中创建一个名为testuser的用户,并赋予其仅查看权限。测试脚本中通过Authorization头传递Token,例如:Authorization: Bearer 。这样能防止因权限过高导致的误操作,同时保障测试环境的安全。测试账号的密码记得用环境变量存储,比如export HARBOR_TEST_PASSWORD="abc123",避免硬编码在脚本中。 在执行测试用例时,务必设置TestNG或JUnit的参数,例如:-Dtest=IntegrationTest。这样能区分不同测试阶段,比如单元测试和集成测试。测试脚本中加入LOG.info("Test step: ..."),能快速定位执行流程。例如,在测试推送镜像前,先打印当前时间,再执行操作,最后再打印一次时间,这样能判断耗时。当测试失败时,通过日志快速判断是API问题还是代码问题,提高排查效率。 常见踩坑场景之一是测试环境变量不一致。比如,HARBOR_URL写成了localhost,但实际在CI系统中是host.docker.internal。这种情况下,测试脚本会一直提示连接失败。解决方案是将所有变量统一放在.env文件中,并通过docker-compose加载环境变量,例如:docker-compose -f docker-compose.test.yml -e .env up。这样能确保各环境使用相同的变量,避免配置错误。 还有人会误用docker run启动Harbor容器,导致网络配置问题。例如,在测试时直接运行docker run -d -p 8080:80 harbor,可能导致容器无法访问。正确的做法是使用docker-compose来管理网络,例如在docker-compose.yml中配置networks: harbor-net,并在启动时指定--network harbor-net。这样能确保容器之间通信顺畅,避免IP冲突。 API路径错误也是常见问题之一。比如,把GET /v2/_catalog写成GET /v2/catalog,导致返回404。这种情况下,需要在脚本中加入异常处理,比如try-catch块,捕获HTTP状态码并打印日志。例如,使用RestAssured的statusCode()方法验证响应码是否为200,而不是直接返回数据。这样能快速识别API路径错误,避免全测失败。 测试用例执行时,如果测试账号权限不足,会导致一系列操作失败,比如拉取镜像或推送镜像。例如,推送镜像时,如果用户没有写权限,会返回403。解决方案是,在脚本中先检查用户权限,使用GET /api/v2.0/users/来获取用户信息,并查看其权限列表。如果权限不足,可以临时提升权限,或者在测试前确保用户有足够的权限。 性能影响方面,Harbor自动化测试比手动测试效率高300%以上。例如,手动测试需要多次登录、操作,而自动化脚本可以在几秒内完成所有流程。但要注意的是,测试环境的负载过高时,可能会导致API响应变慢。比如,同时运行多个测试线程,可能会让Harbor的API请求超时。这时候需要调低并发数,或者使用docker-compose控制资源分配,比如设置memory和cpu限制。 在适用场景方面,Harbor自动化测试适合用于持续集成和回归测试。例如,在Jenkins中设置定时任务,每晚运行一次测试,确保Harbor功能正常。但局限性在于,测试无法覆盖所有用户交互,比如UI层面的错误。例如,页面加载失败、按钮点击异常等,这些都需要手动测试。因此,自动化测试应作为补充,而不是全部。 替代方案方面,推荐使用Selenium配合Harbor的Web UI做UI测试,但这种方式不稳定,容易受浏览器兼容性影响。比如,Chrome和Firefox在元素定位时可能会有差异,导致脚本偶尔报错。进阶技巧是结合Jenkins Pipeline实现测试自动化,例如在Jenkinsfile中编写阶段,包括构建、测试和报告生成。这种方式能实现端到端的自动化流程,减少人为干预。 测试报告生成是自动化测试的重要环节。推荐使用JUnit的XML格式,因为它兼容性强,可直接集成到CI系统中。例如,通过mvn test -Dtest=IntegrationTest来生成报告,再使用Jenkins的JUnit插件解析结果。这样能快速识别失败用例,并生成对应的日志。同时,建议将报告保存到指定目录,比如/target/surefire-reports/,避免文件混乱。 测试脚本中的日志管理至关重要。例如,在测试开始时打印测试环境信息,包括Harbor版本、测试账号、测试镜像等。这样能帮助后续排查问题。同时,测试日志应包含详细的操作步骤,比如"正在推送镜像到测试仓库",而不是只显示结果。使用LOG.info("正在推送镜像到测试仓库")能提升日志可读性,方便调试。 测试依赖项管理也需要注意。例如,测试镜像需要预先构建好,否则会导致测试失败。建议使用docker build命令构建镜像,并通过docker tag设置标签,例如docker tag myimage:latest myimage:test。这样能确保测试镜像和正式镜像区分明确,避免混淆。同时,在测试脚本中加入镜像检查逻辑,例如运行docker images命令,确保镜像存在后再执行测试。 测试执行时,如果遇到镜像不存在的问题,往往是因为没有正确推送镜像。比如,在测试拉取镜像前,先确保镜像已存在。使用docker push命令推送镜像,并检查返回状态码是否为200。同时,在测试脚本中加入等待时间,例如Thread.sleep(5000),确保镜像已完全推送后再进行后续操作。 测试用例设计时,要覆盖关键功能点,比如登录、仓库创建、镜像推送、镜像删除等。每个用例应独立运行,避免相互影响。例如,测试推送镜像后,再测试删除镜像,确保删除操作不会影响其他测试用例。同时,测试用例应包含预期结果和实际结果对比,比如assertThat(actualResult, equalTo(expectedResult)),这样能精准判断测试是否通过。 测试中遇到网络问题时,要检查Docker网络配置是否正确。例如,使用docker network ls查看是否存在名为harbor-net的网络,并通过docker network inspect harbor-net确认其配置。如果网络配置错误,会导致容器无法通信,测试失败。此外,在测试脚本中加入网络检查逻辑,例如运行ping命令测试Harbor服务是否可达,确保网络状态正常。





