Automating UI Tests in GoLang programming Using ChromeDP

Pradap Pandiyan
5 min readSep 30, 2024

--

UI automation testing has become essential for modern web applications to ensure functionality, usability, and performance across different environments. While languages like Python and Java are often associated with test automation, Go (Golang) is becoming a popular choice due to its simplicity, concurrency support, and speed. In this article, we will explore how to build and run UI automation tests using the ChromeDP library in Go. Specifically, we will create and execute multiple tests, run them in headed mode, and generate results.

Why Use Go for UI Automation?

  • Speed: Go is fast, which is a huge advantage when running test suites with hundreds of UI tests.
  • Concurrency: Go’s built-in concurrency (goroutines) can be leveraged to parallelize test execution.
  • Simplicity: Go’s minimalistic syntax allows you to write readable and maintainable test scripts.
  • ChromeDP: A headless Chrome/Chromium library that allows control over the browser directly from Go.

What is ChromeDP?

ChromeDP is a Go library that allows developers to control Chrome/Chromium through the Chrome DevTools Protocol. With ChromeDP, you can interact with a web page, simulate user input, navigate through the browser, and extract content for validation. It works both in headless mode (without a browser UI) and headed mode (with a visible browser).

Setting Up the Environment

To get started with UI testing in Go using ChromeDP, you need to set up your development environment.

  1. Install Go:
    Ensure that you have Go installed on your system. You can download it from golang.org.
  2. Install ChromeDP:
    Use the following command to install the chromedp package:
go get -u github.com/chromedp/chromedp

3. Install a Web Browser:
ChromeDP controls a Chrome or Chromium browser instance. Ensure that you have either of these installed on your machine.

A Sample UI Test Using Go and ChromeDP

Let’s write a Go program that performs a simple UI automation test — navigating to Google, performing a search, and verifying the search results.

main.go – The Core Test

This code will navigate to Google, search for “Golang,” and verify if the term “Golang” appears in the search results.

package main
import (
"context"
"fmt"
"log"
"strings"
"time"
"github.com/chromedp/chromedp"
"github.com/chromedp/chromedp/kb"
)
func main() {
opts := chromedp.DefaultExecAllocatorOptions[:]
opts = append(opts,
chromedp.Flag("headless", false), // Disable headless mode
chromedp.Flag("disable-gpu", false), // Enable GPU (optional)
chromedp.Flag("start-maximized", true),// Start with a maximized window
)
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")
}
}

Running the Test in Headed Mode

The above test runs in headed mode (with the browser visible), as the chromedp.Flag("headless", false) disables headless mode. This is useful for debugging, as you can visually confirm the behavior.

You can run the test with:

go run main.go

Writing Multiple UI Tests Using Go’s Testing Framework

To scale this, we’ll use Go’s built-in testing package and move the tests into a separate file, main_test.go. We'll write three test cases:

  1. Check that the search results contain the term “Golang”.
  2. Verify that the search bar is visible on the Google homepage.
  3. Check if an empty query results in no search results.

main_test.go – Multiple Test Functions

package main
import (
"context"
"strings"
"testing"
"time"
"github.com/chromedp/chromedp"
"github.com/chromedp/chromedp/kb"
)
// TestGoogleSearch_Golang 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")
}
}
// TestGoogleSearch_SearchBarVisible 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")
}
}
// TestGoogleSearch_EmptyQuery 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")
}
}

Running the Tests

Place main.go and main_test.go in the same directory. To run the tests, use the following command:

go test -v

This will execute all the tests in main_test.go, and you'll see logs or error messages depending on whether each test passes or fails.

Conclusion

Using Go and ChromeDP, you can easily write UI automation tests that are both powerful and efficient. Go’s testing framework allows for easy scaling by adding more tests as needed. ChromeDP’s support for both headless and headed modes offers flexibility when running tests locally or in CI environments.

With this setup, you’re ready to automate and test your web applications using Golang!

I have created a project on GitHub and added the code here.

Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏

--

--

Pradap Pandiyan

I’m a passionate QA Engineer. I’m a motovlogger, content creator, off-roader and freelancer. Buy me a coffee here https://www.buymeacoffee.com/pradappandiyan