{cmd,internal}/screentest: add config for remote debugger url
To have test runs output consistent screenshots across
different systems we allow for the use of a remote
instance of Chrome by providing a url to its debugger
as a flag. For example:
go run ./cmd/screentest -d ws://localhost:9222
This is useful in a CI/CD environment to control the
chrome version and OS in which screenshots are taken.
Change-Id: I09b2e2d8e3056d7229808a57653d641677fc8cc3
Reviewed-on: https://go-review.googlesource.com/c/website/+/378475
Run-TryBot: Jamal Carvalho <jamal@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Trust: Jamal Carvalho <jamalcarvalho@google.com>
diff --git a/cmd/screentest/main.go b/cmd/screentest/main.go
index 615c324..a2a2129 100644
--- a/cmd/screentest/main.go
+++ b/cmd/screentest/main.go
@@ -13,6 +13,8 @@
variables provided to script templates as comma separated KEY:VALUE pairs
-c
number of testcases to run concurrently
+ -d
+ chrome debugger url
*/
package main
@@ -32,6 +34,7 @@
update = flag.Bool("u", false, "update cached screenshots")
vars = flag.String("v", "", "variables provided to script templates as comma separated KEY:VALUE pairs")
concurrency = flag.Int("c", (runtime.NumCPU()+1)/2, "number of testcases to run concurrently")
+ debuggerURL = flag.String("d", "", "chrome debugger url")
)
func main() {
@@ -60,7 +63,13 @@
parsedVars[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
}
- if err := screentest.CheckHandler(glob, *update, *concurrency, parsedVars); err != nil {
+ opts := screentest.CheckOptions{
+ Update: *update,
+ MaxConcurrency: *concurrency,
+ Vars: parsedVars,
+ DebuggerURL: *debuggerURL,
+ }
+ if err := screentest.CheckHandler(glob, opts); err != nil {
log.Fatal(err)
}
}
diff --git a/internal/screentest/screentest.go b/internal/screentest/screentest.go
index 6aa2262..bfa8bf1 100644
--- a/internal/screentest/screentest.go
+++ b/internal/screentest/screentest.go
@@ -128,9 +128,28 @@
"google.golang.org/api/iterator"
)
+type CheckOptions struct {
+ // Update is true if cached screenshots should be udpated.
+ Update bool
+
+ // MaxConcurrency is the maximum number of testcases to run in parallel.
+ MaxConcurrency int
+
+ // Vars are accessible as values in the test script templates.
+ Vars map[string]string
+
+ // DebuggerURL is the URL to a chrome websocket debugger. If left empty
+ // screentest tries to find the Chrome exectuable on the system and starts
+ // a new instance.
+ DebuggerURL string
+}
+
// CheckHandler runs the test scripts matched by glob. If any errors are
// encountered, CheckHandler returns an error listing the problems.
-func CheckHandler(glob string, update bool, maxConcurrency int, vars map[string]string) error {
+func CheckHandler(glob string, opts CheckOptions) error {
+ if opts.MaxConcurrency < 1 {
+ opts.MaxConcurrency = 1
+ }
now := time.Now()
ctx := context.Background()
files, err := filepath.Glob(glob)
@@ -140,14 +159,19 @@
if len(files) == 0 {
return fmt.Errorf("no files match %q", glob)
}
- ctx, cancel := chromedp.NewExecAllocator(ctx, append(
- chromedp.DefaultExecAllocatorOptions[:],
- chromedp.WindowSize(browserWidth, browserHeight),
- )...)
+ var cancel context.CancelFunc
+ if opts.DebuggerURL != "" {
+ ctx, cancel = chromedp.NewRemoteAllocator(ctx, opts.DebuggerURL)
+ } else {
+ ctx, cancel = chromedp.NewExecAllocator(ctx, append(
+ chromedp.DefaultExecAllocatorOptions[:],
+ chromedp.WindowSize(browserWidth, browserHeight),
+ )...)
+ }
defer cancel()
var buf bytes.Buffer
for _, file := range files {
- tests, err := readTests(file, vars)
+ tests, err := readTests(file, opts.Vars)
if err != nil {
return fmt.Errorf("readTestdata(%q): %w", file, err)
}
@@ -160,9 +184,9 @@
ctx, cancel = chromedp.NewContext(ctx, chromedp.WithLogf(log.Printf))
defer cancel()
var hdr bool
- runConcurrently(len(tests), maxConcurrency, func(i int) {
+ runConcurrently(len(tests), opts.MaxConcurrency, func(i int) {
tc := tests[i]
- if err := tc.run(ctx, update); err != nil {
+ if err := tc.run(ctx, opts.Update); err != nil {
if !hdr {
fmt.Fprintf(&buf, "%s\n\n", file)
hdr = true
@@ -180,8 +204,19 @@
return nil
}
+type TestOpts struct {
+ // Update is true if cached screenshots should be udpated.
+ Update bool
+
+ // Parallel runs t.Parallel for each testcase.
+ Parallel bool
+
+ // Vars are accessible as values in the test script templates.
+ Vars map[string]string
+}
+
// TestHandler runs the test script files matched by glob.
-func TestHandler(t *testing.T, glob string, update, parallel bool, vars map[string]string) {
+func TestHandler(t *testing.T, glob string, opts TestOpts) {
ctx := context.Background()
files, err := filepath.Glob(glob)
if err != nil {
@@ -196,7 +231,7 @@
)...)
defer cancel()
for _, file := range files {
- tests, err := readTests(file, vars)
+ tests, err := readTests(file, opts.Vars)
if err != nil {
t.Fatal(err)
}
@@ -207,10 +242,10 @@
defer cancel()
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- if parallel {
+ if opts.Parallel {
t.Parallel()
}
- if err := tc.run(ctx, update); err != nil {
+ if err := tc.run(ctx, opts.Update); err != nil {
t.Fatal(err)
}
})
diff --git a/internal/screentest/screentest_test.go b/internal/screentest/screentest_test.go
index 96838ac..fac5d55 100644
--- a/internal/screentest/screentest_test.go
+++ b/internal/screentest/screentest_test.go
@@ -239,7 +239,7 @@
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if err := CheckHandler(tt.args.glob, false, 1, nil); (err != nil) != tt.wantErr {
+ if err := CheckHandler(tt.args.glob, CheckOptions{}); (err != nil) != tt.wantErr {
t.Fatalf("CheckHandler() error = %v, wantErr %v", err, tt.wantErr)
}
if len(tt.wantFiles) != 0 {
@@ -262,7 +262,7 @@
if err != nil {
t.Skip()
}
- TestHandler(t, "testdata/pass.txt", false, false, nil)
+ TestHandler(t, "testdata/pass.txt", TestOpts{})
}
func TestHeaders(t *testing.T) {