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-多种测试结果
测试用例:
- 检查搜索结果是否包含术语“Golang”
- 验证搜索栏是否在 Google 主页上可见
- 检查空查询是否会导致没有搜索结果
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
测试结果