当前位置: 首页 > article >正文

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

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.kler.cn/a/454639.html

相关文章:

  • 蓝桥杯速成教程{三}(adc,i2c,uart)
  • js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)
  • 五十七:RST_STREAM帧及常见错误码
  • Markdown语法字体字号讲解
  • Thinkphp 使用workerman消息实现消息推送完整示例
  • 【MySQL】SQL 优化经验
  • uniapp 文本转语音
  • 挑战一个月基本掌握C++(第十二天)了解命名空间,模板,预处理器
  • 前端Python应用指南(五)用FastAPI快速构建高性能API
  • 同步异步日志系统:设计模式
  • ubuntu 账号从文本中的1000,改成0,后五笔输入法等中文输入法不可用,如何改回来
  • 【Ubuntu 20.4安装截图软件 flameshot 】
  • 全面Kafka监控方案:从配置到指标
  • 【自由能系列(初级),论文解读】神经网络中,熵代表系统的不确定性,自由能则引导系统向更低能量的状态演化,而动力学则描述了系统状态随时间的变化。
  • flask后端开发(11):User模型创建+注册页面模板渲染
  • 使用Python实现自动化文档生成工具:提升文档编写效率的利器
  • STM32F103RCT6学习之一:基本开发流程
  • FileLink为企业打造了一站式的跨网安全文件共享解决方案
  • Docker使用——国内Docker的安装办法
  • 前端面试题合集(一)——HTML/CSS/Javascript/ES6
  • Kubernetes Gateway API-2-跨命名空间路由
  • 鸿蒙Next自定义相机开发时,如何解决相机在全屏预览的时候,画面会有变形和拉伸?
  • 【Agent】Chatbot、Copilot与Agent如何帮助我们的提升效率?
  • 【js】记录预览pdf文件
  • 如何从 0 到 1 ,打造全新一代分布式数据架构
  • Jenkins 命令行多线程并发下载制品包