Go+chromedp实现Web UI自动化测试

news2025/1/5 7:40:37

1.为什么使用go进行UI自动化测试?

速度:Go速度很快,这在运行包含数百个UI测试的测试套件时是一个巨大的优势

并发性:可以利用Go的内置并发性(goroutines)来并行化测试执行

简单:Go的简约语法允许您编写可读且可维护的测试脚本

ChromeDP:一个无头Chrome/Chromium库,允许直接从Go控制浏览器

2.什么是chromedp?

ChromeDP 是一个 Go 库,允许开发者通过 Chrome DevTools 协议控制 Chrome/Chromium。借助 ChromeDP,您可以与网页交互、模拟用户输入、浏览浏览器以及提取内容进行验证。它既可以在无头模式(没有浏览器UI)下工作,也可以在有头模式(有可见浏览器)下工作。

3.设置环境

安装go

brew install go

安装ChromeDP

go get -u github.com/chromedp/chromedp

4.编写代码

示例测试

打开GoLand,新建main.go文件

main.go-核心测试

这段代码将会打开Chrome,导航到Google搜索页,搜索"Golang",并验证Golang是否出现在搜索结果中

package main

import (
   "context"
   "fmt"
   "github.com/chromedp/chromedp"
   "github.com/chromedp/chromedp/kb"
   "log"
   "strings"
   "time"
)

func main() {
   opts := chromedp.DefaultExecAllocatorOptions[:]
   opts = append(opts,
      // Disable headless mode
      chromedp.Flag("headless", false),
      // Enable GPU (optional)
      chromedp.Flag("disable-gpu", false),
      // Start with a maximized window
      chromedp.Flag("start-maximized", true),
   )
   allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
   defer cancel()
   ctx, cancel := chromedp.NewContext(allocCtx)
   defer cancel()
   ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
   defer cancel()
   var result string
   err := chromedp.Run(ctx,
      chromedp.Navigate("https://www.google.com"),
      chromedp.WaitVisible(`//textarea[@name="q"]`),
      chromedp.SendKeys(`//textarea[@name="q"]`, "Golang"),
      chromedp.SendKeys(`//textarea[@name="q"]`, kb.Enter),
      chromedp.WaitVisible(`#search`),
      chromedp.Text(`#search`, &result),
   )
   if err != nil {
      log.Fatal(err)
   }
   if strings.Contains(result, "Golang") {
      fmt.Println("Test Passed: 'Golang' found in search results")
   } else {
      fmt.Println("Test Failed: 'Golang' not found in search results")
   }
}

Go测试框架编写多个UI测试

新建main_test.go文件

main_test.go-多种测试结果

测试用例:

  1. 检查搜索结果是否包含术语“Golang”
  2. 验证搜索栏是否在 Google 主页上可见
  3. 检查空查询是否会导致没有搜索结果
package main

import (
   "context"
   "github.com/chromedp/chromedp"
   "github.com/chromedp/chromedp/kb"
   "strings"
   "testing"
   "time"
)

// checks that the search results contain "Golang"
func TestGoogleSearch_Golang(t *testing.T) {
   opts := chromedp.DefaultExecAllocatorOptions[:]
   opts = append(opts,
      chromedp.Flag("headless", false),
      chromedp.Flag("disable-gpu", false),
      chromedp.Flag("start-maximized", true),
   )
   allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
   defer cancel()
   ctx, cancel := chromedp.NewContext(allocCtx)
   defer cancel()
   ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
   defer cancel()
   var result string
   err := chromedp.Run(ctx,
      chromedp.Navigate("https://www.google.com"),
      chromedp.WaitVisible(`//textarea[@name="q"]`),
      chromedp.SendKeys(`//textarea[@name="q"]`, "Golang"),
      chromedp.SendKeys(`//textarea[@name="q"]`, kb.Enter),
      chromedp.WaitVisible(`#search`),
      chromedp.Text(`#search`, &result),
   )
   if err != nil {
      t.Fatalf("Test Failed: %v", err)
   }
   if strings.Contains(result, "Golang") {
      t.Log("Test Passed: 'Golang' found in search results")
   } else {
      t.Errorf("Test Failed: 'Golang' not found in search results")
   }
}

// checks that the search bar is visible
func TestGoogleSearch_SearchBarVisible(t *testing.T) {
   opts := chromedp.DefaultExecAllocatorOptions[:]
   opts = append(opts,
      chromedp.Flag("headless", false),
      chromedp.Flag("disable-gpu", false),
      chromedp.Flag("start-maximized", true),
   )
   allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
   defer cancel()
   ctx, cancel := chromedp.NewContext(allocCtx)
   defer cancel()
   ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
   defer cancel()
   err := chromedp.Run(ctx,
      chromedp.Navigate("https://www.google.com"),
      chromedp.WaitVisible(`//textarea[@name="q"]`),
   )
   if err != nil {
      t.Errorf("Test Failed: Search bar not visible - %v", err)
   } else {
      t.Log("Test Passed: Search bar is visible")
   }
}

// checks if there are results when the search query is empty
func TestGoogleSearch_EmptyQuery(t *testing.T) {
   opts := chromedp.DefaultExecAllocatorOptions[:]
   opts = append(opts,
      chromedp.Flag("headless", false),
      chromedp.Flag("disable-gpu", false),
      chromedp.Flag("start-maximized", true),
   )
   allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
   defer cancel()
   ctx, cancel := chromedp.NewContext(allocCtx)
   defer cancel()
   ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
   defer cancel()
   var result string
   err := chromedp.Run(ctx,
      chromedp.Navigate("https://www.google.com"),
      chromedp.WaitVisible(`//textarea[@name="q"]`),
      chromedp.SendKeys(`//textarea[@name="q"]`, ""), // Empty query
      chromedp.SendKeys(`//textarea[@name="q"]`, kb.Enter),
      chromedp.WaitVisible(`#search`, chromedp.ByID),
      chromedp.Text(`#search`, &result),
   )
   if err != nil {
      t.Fatalf("Test Failed: %v", err)
   }
   if result == "" {
      t.Log("Test Passed: No search results for empty query")
   } else {
      t.Errorf("Test Failed: Unexpected results for empty query")
   }
}

执行测试

将main.go和main_test.go放在同一目录,然后执行命令

go test -v

测试结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

总结TCP/IP四层模型

总结TCP/IP四层模型 阅读目录(Content) 一、TCP/IP参考模型概述 1.1、TCP/IP参考模型的层次结构二、TCP/IP四层功能概述 2.1、主机到网络层  2.2、网络互连层  2.3、传输层  2.3、应用层 三、TCP/IP报文格式 3.1、IP报文格式3.2、TCP数据段格式3.3、UDP数据段格式3.4、套…

怎么在家访问公司服务器?

在日常工作中,特别是对信息技术从业者而言,工作往往离不开公司的服务器。他们需要定期访问服务器,获取一些关键的机密文件或数据。如果您在家办公,并且需要处理未完成的任务,同时需要从公司服务器获取所需的数据&#…

自动化文档处理:Azure AI Document Intelligence

Azure AI Document Intelligence支持多种文件格式,包括PDF、JPEG、PNG等。其核心功能是将这些文档按页进行内容提取,并转化为LangChain文档。其默认输出格式是Markdown,这使得文档可以通过MarkdownHeaderTextSplitter进行语义分片。您也可以使…

ubuntu快速入门

1.进入某个文件夹 cd workspace/2.tab自动补全 3.列出当前文件夹所有文件 ls列出所有文件包括隐藏文件 ls -a 4.创建文件夹 mkdir linuxLearn 5.创建文件 gedit command.sh在commmand.sh键入 echo hello echo hi? echo how are you? PS:touch hello.txt(也可以创建新…

在虚幻引擎4(UE4)中使用蓝图的详细教程

在虚幻引擎4(UE4)中使用蓝图的详细教程 虚幻引擎4(Unreal Engine 4,简称UE4)是一款功能强大的游戏引擎,广泛应用于游戏开发、虚拟现实、建筑可视化等领域。UE4 提供了一个强大的可视化脚本工具——蓝图&am…

修改网络ip地址方法有哪些?常用的有这四种

在数字时代,IP地址作为网络设备的唯一标识,对于网络连接和通信至关重要。然而,有时候我们可能需要修改设备的IP地址,以满足特定的网络需求或解决网络问题。本文将为您详细介绍几种修改网络IP地址的常用方法,无论是对于…

你了解DNS吗?

你了解DNS吗? 一. 介绍二. DNS的工作原理三. DNS查询流程示意图四. DNS 记录类型五. DNS的安全问题与 DNSSEC 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 一. 介绍 …

Android笔试面试题AI答之非技术问题(3)

Android入门请看《Android应用开发项目式教程》 文章目录 1.你是如何应付项目经理的?**1. 建立清晰的沟通机制****2. 明确项目目标与优先级****3. 制定合理的开发计划****4. 管理项目风险****5. 推动敏捷开发****6. 管理需求变更****7. 提升团队协作****8. 关注项目…

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后,Design Compiler内置的HDL Compiler工…

操作012:延迟插件

文章目录 操作012:延迟插件一、插件简介二、插件安装1、确定卷映射目录2、下载延迟插件3、启用插件4、确认 三、创建交换机四、代码测试1、生产者端代码2、消费者端代码①情况A:资源已创建②情况B:资源未创建 3、执行效果①交换机类型②生产者…

Kafka 性能提升秘籍:涵盖配置、迁移与深度巡检的综合方案

文章目录 1.1.网络和io操作线程配置优化1.2.log数据文件刷盘策略1.3.日志保留策略配置1.4.replica复制配置1.5.配置jmx服务1.6.系统I/O参数优化1.6.1.网络性能优化1.6.2.常见痛点以及优化方案1.6.4.优化参数 1.7.版本升级1.8.数据迁移1.8.1.同集群broker之间迁移1.8.2.跨集群迁…

【文献精读笔记】Explainability for Large Language Models: A Survey (大语言模型的可解释性综述)(二)

****非斜体正文为原文献内容(也包含笔者的补充),灰色块中是对文章细节的进一步详细解释! 3.1.2 基于注意力的解释(Attention-Based Explanation) 注意力机制可以揭示输入数据中各个部分之间的关系&#…

音视频采集推流时间戳记录方案

音视频同步更多文章 深入理解音视频pts,dts,time_base以及时间数学公式_视频pts计算-CSDN博客 ffplay音视频同步分析_ffplay 音视频同步-CSDN博客 音视频采集打时间戳设计 实时音视频数据的采集和处理场景。具体来说: 采集阶段: 在音视频数据采集过…

「numpy」numpy初步、ndarray、创建数组

Numpy 初步、ndarray、创建数组 【目录】 简介 ndarray介绍 ndarray用法 ndarray基本操作 一、numpy简介 Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。 Numpy支持常见的数组和矩阵操作。对于同样…

FFmpeg 编码和解码

文章目录 音频格式AACADIF音频数据交换格式ADTS音频数据传输流 音频解码音频编码 视频格式H264GOP图像组I帧,P帧,B帧H264压缩技术H264压缩级别H264视频级别H264码流结构SPSPPS 解码视频编码视频 音频格式 AAC AAC全称 Advanced Audio Coding&#xff0…

游戏引擎学习第67天

reviewing “apron”概念以更新区域 我们正在进行模拟区域的扩展工作,目标是通过增加一个更大的区域来支持更丰富的互动,尤其是那些可能超出摄像机视野的内容。现有的模拟区域包括摄像机能看到的区域和其周围的环境区域,但为了保证更高效的游…

3D线上艺术展:艺术与技术的完美融合

随着数字技术的飞速发展,未来的艺术展览正逐步迈向线上线下融合的新阶段。其中,3D线上展览以其独特的魅力,成为线下展览的延伸与拓展,为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言,3D线上展览不仅打…

Qt制作一个简单闹钟

增加testtospeech模块 QT core gui texttospeech 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> #include <QTimer> #include <QTime> #include <QMouseEvent> #include <QTextToSpeech>…

Java编程题_面向对象和常用API01_B级

Java编程题_面向对象和常用API01_B级 第1题 面向对象、异常、集合、IO 题干: 请编写程序&#xff0c;完成键盘录入学生信息&#xff0c;并计算总分将学生信息与总分一同写入文本文件 需求&#xff1a;键盘录入3个学生信息(姓名,语文成绩,数学成绩) 求出每个学生的总分 ,并…

tcpdump 网络数据包分析工具

简介 用简单的话来定义tcpdump&#xff0c;就是&#xff1a;dump the traffic on a network&#xff0c;根据使用者的定义对网络上的数据包进行截获的包分析工具。 tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的…