A production-quality end-to-end test framework built with Go and Playwright. Designed as a starting point for QA engineers who want to write browser automation tests in Go.
graph TD
A[Test Files] --> B[Page Objects]
A --> C[Test Helpers]
B --> D[BasePage]
C --> E[BrowserManager]
C --> F[Screenshot Helper]
C --> G[Report Generator]
E --> H[Playwright-Go]
H --> I[Chromium]
H --> J[Firefox]
H --> K[WebKit]
subgraph Config
L[config.yaml] --> M[Config Loader]
N[Env Variables] --> M
end
M --> E
M --> F
M --> G
graph LR
subgraph "Page Object Model"
BP[BasePage<br/>Navigate, WaitFor] --> TP[TodoPage]
BP --> LP[LoginPage]
BP --> DLP[DynamicLoadingPage]
BP --> DP[DropdownPage]
end
playwright-go-framework/
├── .github/workflows/ci.yml # GitHub Actions CI (multi-browser matrix)
├── config/
│ └── config.go # Configuration management (YAML + env vars)
├── helpers/
│ ├── browser.go # Browser lifecycle (launch, context, page)
│ ├── screenshot.go # Screenshot capture utilities
│ └── report.go # HTML/JSON test report generation
├── pages/
│ ├── base_page.go # Shared page methods (navigation, waits)
│ ├── todo_page.go # TodoMVC page object
│ ├── login_page.go # Login form page object
│ ├── dynamic_loading_page.go # Dynamic loading page object
│ └── dropdown_page.go # Dropdown page object
├── tests/
│ ├── setup_test.go # TestMain — global browser lifecycle
│ ├── todo_test.go # TodoMVC tests (add, complete, filter, delete)
│ ├── login_test.go # Login tests (valid, invalid, logout flow)
│ ├── dynamic_loading_test.go # Wait/async loading tests
│ ├── dropdown_test.go # Form interaction tests
│ ├── screenshot_test.go # Screenshot capture tests
│ └── network_test.go # Network interception & mocking tests
├── config.yaml # Default configuration
├── Dockerfile # Container for CI/headless runs
├── docker-compose.yml # Docker Compose for easy test execution
├── Makefile # Common tasks
└── README.md
- Go 1.22+
- Git
# Clone the repository
git clone https://github.com/qambar/playwright-go-framework.git
cd playwright-go-framework
# Install dependencies and Playwright browsers
make install# Run all tests (Chromium, headless)
make test
# Run with a specific browser
make test-firefox
make test-webkit
# Run in headed mode (see the browser)
make test-headed
# Run with gotestsum for better output
make test-verbose
# Generate test reports
make test-report# Run tests in Docker (no local browser install needed)
make docker-test
# Or with a specific browser
BROWSER=firefox docker compose run --rm testsConfiguration is loaded in order of precedence:
- Environment variables (highest priority)
- config.yaml file
- Default values (built into code)
| Variable | Default | Description |
|---|---|---|
BASE_URL |
https://the-internet.herokuapp.com |
Base URL for tests |
BROWSER |
chromium |
Browser: chromium, firefox, webkit |
HEADLESS |
true |
Run browser headless |
SLOW_MO |
0 |
Slow down operations (ms) |
TIMEOUT |
30000 |
Default timeout (ms) |
SCREENSHOT_ON_FAILURE |
true |
Auto-capture on test failure |
SCREENSHOT_DIR |
reports/screenshots |
Screenshot output directory |
package pages
import "github.com/playwright-community/playwright-go"
type MyPage struct {
*BasePage
heading playwright.Locator
button playwright.Locator
}
func NewMyPage(page playwright.Page) *MyPage {
return &MyPage{
BasePage: NewBasePage(page),
heading: page.Locator("h1"),
button: page.Locator("#submit"),
}
}
func (mp *MyPage) Goto() error {
return mp.Navigate("/my-page")
}
func (mp *MyPage) GetHeading() (string, error) {
return mp.heading.TextContent()
}package tests
import (
"testing"
"github.com/qambar/playwright-go-framework/helpers"
"github.com/qambar/playwright-go-framework/pages"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMyPage_Heading(t *testing.T) {
t.Parallel()
page := helpers.SetupTest(t)
mp := pages.NewMyPage(page)
require.NoError(t, mp.Goto())
heading, err := mp.GetHeading()
require.NoError(t, err)
assert.Equal(t, "Expected Heading", heading)
}helpers.SetupTest(t)— Creates an isolated browser context + page, registers cleanup, captures screenshot on failuret.Parallel()— Tests run in parallel by default; each gets its own browser contextrequire.NoError— Stops the test immediately on error (use for setup steps)assert.Equal— Records failure but continues (use for assertions)
| Test | Playwright Features Demonstrated |
|---|---|
todo_test.go |
Navigation, form input, DOM assertions, element interaction |
login_test.go |
Form submission, text content verification, visibility checks |
dynamic_loading_test.go |
Auto-waiting, explicit waits, async content |
dropdown_test.go |
Select/dropdown interaction, option selection |
screenshot_test.go |
Full-page screenshots, element screenshots |
network_test.go |
Route interception, response mocking, request waiting |
The GitHub Actions pipeline runs tests across all three browsers in parallel:
- Chromium, Firefox, WebKit via matrix strategy
- Test reports uploaded as artifacts
- Screenshots captured and uploaded on failure
golangci-lintfor code quality