-
Notifications
You must be signed in to change notification settings - Fork 795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
example: using the x/exp/teatest package #352
Conversation
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
Is this PR a candidate for merging anytime soon? I have been using bubbletea for a little while now, it is a fantastic library, but it does mean you end up with a program that is largely untested through automation. I have been thinking of writing my own library for testing bubbletea, but noticed this PR. |
@purpleclay we're trying it out in some places to see how it feels like... if you wanna give it a try and let us know what you think, it would be greatly appreciated as well (and you can help driving how it should look like). You can play with it by getting this branch instead: go get github.com/charmbracelet/bubbletea@test |
@caarlos0 sure I will try it out on my current project. I guess the only question I would have while trying to use the current flavour of |
@purpleclay you can run |
Hi @caarlos0 I have attempted to use https:/purpleclay/dns53/blob/teatest/internal/tui/dashboard_test.go So here are my observations (btw I am liking the fact I can test my TUI):
data race details==================
WARNING: DATA RACE
Write at 0x00c0003b7eb0 by goroutine 8:
bytes.(*Buffer).Write()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:169 +0x44
fmt.Fprintf()
/usr/local/Cellar/go/1.18.3/libexec/src/fmt/print.go:205 +0xb1
github.com/charmbracelet/bubbletea.clearLine()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/screen.go:19 +0x85
github.com/charmbracelet/bubbletea.(*standardRenderer).stop()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/standard_renderer.go:75 +0x31
github.com/charmbracelet/bubbletea.(*Program).shutdown()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:588 +0xd1
github.com/charmbracelet/bubbletea.(*Program).StartReturningModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:496 +0x1cd1
github.com/charmbracelet/bubbletea.(*Program).Start()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:549 +0x52
github.com/charmbracelet/bubbletea/teatest.TestModel.func1()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:35 +0x53
Previous write at 0x00c0003b7eb0 by goroutine 7:
bytes.(*Buffer).Write()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:169 +0x44
fmt.Fprintf()
/usr/local/Cellar/go/1.18.3/libexec/src/fmt/print.go:205 +0xb1
github.com/charmbracelet/bubbletea.showCursor()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/screen.go:15 +0x4d
github.com/charmbracelet/bubbletea.Program.restoreTerminalState()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tty.go:30 +0x25
github.com/charmbracelet/bubbletea.(*Program).ReleaseTerminal()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:687 +0x164
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:44 +0x378
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 8 (running) created at:
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:34 +0x2fd
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x724
testing.runTests.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1839 +0x99
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.runTests()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1837 +0x7e4
testing.(*M).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1719 +0xa71
main.main()
_testmain.go:99 +0x3a9
==================
==================
WARNING: DATA RACE
Read at 0x00c0003b7e90 by goroutine 8:
bytes.(*Buffer).tryGrowByReslice()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:107 +0x52
bytes.(*Buffer).Write()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:170 +0x18
fmt.Fprintf()
/usr/local/Cellar/go/1.18.3/libexec/src/fmt/print.go:205 +0xb1
github.com/charmbracelet/bubbletea.clearLine()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/screen.go:19 +0x85
github.com/charmbracelet/bubbletea.(*standardRenderer).stop()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/standard_renderer.go:75 +0x31
github.com/charmbracelet/bubbletea.(*Program).shutdown()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:588 +0xd1
github.com/charmbracelet/bubbletea.(*Program).StartReturningModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:496 +0x1cd1
github.com/charmbracelet/bubbletea.(*Program).Start()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:549 +0x52
github.com/charmbracelet/bubbletea/teatest.TestModel.func1()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:35 +0x53
Previous write at 0x00c0003b7e90 by goroutine 7:
bytes.(*Buffer).tryGrowByReslice()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:108 +0xb3
bytes.(*Buffer).Write()
/usr/local/Cellar/go/1.18.3/libexec/src/bytes/buffer.go:170 +0x18
fmt.Fprintf()
/usr/local/Cellar/go/1.18.3/libexec/src/fmt/print.go:205 +0xb1
github.com/charmbracelet/bubbletea.showCursor()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/screen.go:15 +0x4d
github.com/charmbracelet/bubbletea.Program.restoreTerminalState()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tty.go:30 +0x25
github.com/charmbracelet/bubbletea.(*Program).ReleaseTerminal()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:687 +0x164
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:44 +0x378
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 8 (running) created at:
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:34 +0x2fd
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x724
testing.runTests.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1839 +0x99
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.runTests()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1837 +0x7e4
testing.(*M).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1719 +0xa71
main.main()
_testmain.go:99 +0x3a9
==================
==================
WARNING: DATA RACE
Read at 0x00c000156ce8 by goroutine 8:
runtime.racereadrange()
<autogenerated>:1 +0x1b
github.com/charmbracelet/bubbletea.(*Program).StartReturningModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:496 +0x1cd1
github.com/charmbracelet/bubbletea.(*Program).Start()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:549 +0x52
github.com/charmbracelet/bubbletea/teatest.TestModel.func1()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:35 +0x53
Previous write at 0x00c000156ce9 by goroutine 7:
github.com/charmbracelet/bubbletea.(*Program).ReleaseTerminal()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/tea.go:682 +0xc4
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:44 +0x378
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 8 (running) created at:
github.com/charmbracelet/bubbletea/teatest.TestModel()
/Users/purpleclay/go/pkg/mod/github.com/charmbracelet/[email protected]/teatest/teatest.go:34 +0x2fd
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:50 +0x1dc
github.com/purpleclay/dns53/internal/tui_test.TestDashboard()
/Users/purpleclay/dev/github.com/purpleclay/dns53/internal/tui/dashboard_test.go:42 +0x19b
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.(*T).Run.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x47
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1486 +0x724
testing.runTests.func1()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1839 +0x99
testing.tRunner()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1439 +0x213
testing.runTests()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1837 +0x7e4
testing.(*M).Run()
/usr/local/Cellar/go/1.18.3/libexec/src/testing/testing.go:1719 +0xa71
main.main()
_testmain.go:99 +0x3a9
==================
--- FAIL: TestDashboard (0.21s)
testing.go:1312: race detected during execution of test |
Signed-off-by: Carlos A Becker <[email protected]>
ahh, glad you got to test it @purpleclay!
in that example case, the sleep is to ensure some time passed so I can properly test the output... that said, since commands run in another goroutine, it might be needed to either sleep or sync with a
I think you can put a
I think some people might, for simpler outputs...
investigating...
depending on your project, yes... unfortunately.. I don't have a good solution for that... but I'm open to hear any ideas you might have... |
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
@purpleclay the race should be fixed now! |
Awesome. I will give it another try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this!
I'm currently writing tests for a few simple models that build on github.com/charmbracelet/bubbles/textinput.Model
(code in twpayne/chezmoi#2359).
I would like to be able to test for when tea.Model.Update()
returns tea.Quit
as the command, so that I know that my model has terminated correctly. This does not seem to be currently possible as tea.Cmd
is a function. Go only allows for functions to be compared to nil
, and tea.Quit
uses an unexported struct value to signal its value. Would it be possible to add something like:
func IsCmdQuit(cmd tea.Cmd) bool { /* ... *. }
to teatest
so cmd.Quit
s can be tested?
teatest/teatest.go
Outdated
Runes: []rune{rune(c)}, | ||
Type: tea.KeyRunes, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's would also be nice to be able to send tea.KeyMsg
s of different types, e.g. for tea.KeyCtrlC
, etc. There's an initial implementation at https:/twpayne/chezmoi/blob/4f4760f4911ff03fe431ce31bd847a05b213d6a9/pkg/chezmoibubbles/chezmoibubbles_test.go. This converts a string like "a\r"
to the equivalent of the user pressing a
then Enter
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems to make sense as well, will play with it later today 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the delay, I forgot about this...
nevertheless, for that you can use teatest.Send
and send a KeyMsg
directly:
tm.Send(tea.KeyMsg{
Type: tea.KeyEnter,
})
I think it's possible, yes. Will work on this later 🤘 |
@caarlos0 is there a potential timeframe of when this |
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos A Becker <[email protected]>
This looks great; thanks so much for taking a look at that. I'll have to give these latest changes a spin! |
Hello there! I noticed this pull request and I'm wondering if it's still in development? Can you give us an update or any news on the progress? Thank you! |
Signed-off-by: Carlos A Becker <[email protected]>
Okay, our idea is to do the following:
thoughts? |
wait for the underlying context to finish. extract from #352
Allows to check if the given command/message will cause the application to quit. Extracted from #352
Signed-off-by: Carlos A Becker <[email protected]>
Signed-off-by: Carlos Alexandro Becker <[email protected]>
Signed-off-by: Carlos Alexandro Becker <[email protected]>
* feat: tea.Wait wait for the underlying context to finish. extract from #352 * fix: wait til the end of shutdown Signed-off-by: Carlos Alexandro Becker <[email protected]> --------- Signed-off-by: Carlos Alexandro Becker <[email protected]>
Signed-off-by: Carlos Alexandro Becker <[email protected]>
Signed-off-by: Carlos Alexandro Becker <[email protected]>
Signed-off-by: Carlos Alexandro Becker <[email protected]>
Hey everyone! After many months, we're finally releasing the teatest package! It'll live under github.com/charmbracelet/x/exp/teatest, and will have a tagged release once we release bubbletea. Please, do try it out in your projects, and open issues if you find any bugs or possible enhancements. This PR right now contains only an example of teatest usage. Thank you! |
Introducing the
teatest
package - a very small package with testing helpers for bubbletea apps.You basically test a model, giving the model itself, a set of interactions (
tea.Msg
's) and an assertion, which is basically asserting the output against a given golden file.Its a very raw idea, any feedback welcome.