Testing Graphical Apps
Part of a good test suite is being able to quickly write tests and run them on a regular basis. Fyne’s API is designed to make testing applications easy. By separating component logic from its rendering definition we can load applications without actually displaying them and test the functionality completely.
Example
We can demonstrate unit testing by extending our Hello World
app to include space for users to input their name to be greeted.
We start by updating the user interface to have two elements,
a Label
for the greeting and an Entry
for the name input.
We display them, one above another, using container.NewVBox
(a
vertical box container). The updated user interface code will look as follows:
func makeUI() (*widget.Label, *widget.Entry) {
return widget.NewLabel("Hello world!"),
widget.NewEntry()
}
func main() {
a := app.New()
w := a.NewWindow("Hello Person")
w.SetContent(container.NewVBox(makeUI()))
w.ShowAndRun()
}
To test this input behaviour we create a new file (with a name ending
_test.go
to mark it as tests) that defines a TestGreeter
function.
package main
import (
"testing"
)
func TestGreeting(t *testing.T) {
}
We can add an intial test that verifies the initial state, to do this
we test the Text
field of the Label
that is returned from makeUI
and error the test if it is not correct. Add the following code to your test method:
out, in := makeUI()
if out.Text != "Hello world!" {
t.Error("Incorrect initial greeting")
}
This test will pass - next we add to the test to validate the greeter.
We use the Fyne fyne.io/fyne/v2/test
package which assists in
test scenarios, calling test.Type
to simulate user input.
The following test code will check that the output updates when the
user’s name is input (be sure to add the import as well):
test.Type(in, "Andy")
if out.Text != "Hello Andy!" {
t.Error("Incorrect user greeting")
}
You can run all of these tests using go test .
- just like any other tests.
Doing so you will now see a failure - because we did not add the greeter logic. Update the makeUI
function to the following code:
func makeUI() (*widget.Label, *widget.Entry) {
out := widget.NewLabel("Hello world!")
in := widget.NewEntry()
in.OnChanged = func(content string) {
out.SetText("Hello " + content + "!")
}
return out, in
}
Doing so you will see that the tests now pass. You can also run the
full application (using go run .
) and see the greeting update as
you enter a name in the Entry
field.
Notice also that these tests all run without displaying a window
or stealing your mouse - this is another benefit of the Fyne unit
testing setup.