Skip to content

Commit f38739a

Browse files
taptedCommit bot
authored and
Commit bot
committed
Markdown docs for TestBrowserDialog
TestBrowserDialog landed in r440240 and is ready for wider use. Excerpt: `TestBrowserDialog` provides a way to register an `InProcessBrowserTest` testing harness with a framework that invokes Chrome browser dialogs in a consistent way. The contents are taken from the public doc on chromium.org at https://goo.gl/EFz4r2 BUG=654151 Review-Url: https://codereview.chromium.org/2684513002 Cr-Commit-Position: refs/heads/master@{#449200}
1 parent d1065b7 commit f38739a

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed

docs/testing/test_browser_dialog.md

+279
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
# Testing Chrome browser dialogs with TestBrowserDialog
2+
3+
\#include "[chrome/browser/ui/test/test_browser_dialog.h]"
4+
5+
`TestBrowserDialog` provides a way to register an `InProcessBrowserTest` testing
6+
harness with a framework that invokes Chrome browser dialogs in a consistent
7+
way. It optionally provides a way to invoke dialogs "interactively". This allows
8+
screenshots to be generated easily, with the same test data, to assist with UI
9+
review. It also provides a registry of dialogs so they can be systematically
10+
checked for subtle changes and regressions.
11+
12+
[TOC]
13+
14+
## How to register a dialog
15+
16+
If registering an existing dialog, there's a chance it already has a test
17+
harness inheriting, using, or with `typedef InProcessBrowserTest` (or a
18+
descendant of it). If so, using `TestBrowserDialog` is straightforward. Assume
19+
the existing InProcessBrowserTest is in `foo_dialog_browsertest.cc`:
20+
21+
class FooDialogTest : public InProcessBrowserTest { ...
22+
23+
Change this to inherit from DialogBrowserTest, and override
24+
`ShowDialog(std::string)`. See [Advanced Usage](#Advanced-Usage) for details.
25+
26+
```cpp
27+
class FooDialogTest : public DialogBrowserTest {
28+
public:
29+
..
30+
// DialogBrowserTest:
31+
void ShowDialog(const std::string& name) override {
32+
/* Show dialog attached to browser() and leave it open. */
33+
}
34+
..
35+
};
36+
```
37+
38+
Then add test invocations using the usual GTest macros, in
39+
`foo_dialog_browsertest.cc`:
40+
41+
```cpp
42+
IN_PROC_BROWSER_TEST_F(FooDialogTest, InvokeDialog_default) {
43+
RunDialog();
44+
}
45+
```
46+
47+
Notes:
48+
49+
* The body of the test is always just "`RunDialog();`".
50+
* "`default`" is the `std::string` passed to `ShowDialog()` and can be
51+
customized. See
52+
[Testing additional dialog "styles"](#Testing-additional-dialog-styles_).
53+
* The text before `default` (in this case) must always be "`InvokeDialog_`".
54+
55+
### Concrete examples
56+
57+
* [chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc]
58+
* [chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc]
59+
* [chrome/browser/ui/collected_cookies_browsertest.cc]
60+
* [chrome/browser/ui/update_chrome_dialog_browsertest.cc]
61+
62+
## Running the tests
63+
64+
List the available dialogs with
65+
66+
$ ./browser_tests --gtest_filter=BrowserDialogTest.Invoke
67+
68+
E.g. `FooDialogTest.InvokeDialog_default` should be listed. To show the dialog
69+
interactively, run
70+
71+
$ ./browser_tests --gtest_filter=BrowserDialogTest.Invoke --interactive \
72+
--dialog=FooDialogTest.InvokeDialog_default
73+
74+
### Implementation
75+
76+
`BrowserDialogTest.Invoke` searches for gtests that have "`InvokeDialog_`" in
77+
their name, so they can be collected in a list. Providing a `--dialog` argument
78+
will invoke that test case in a subprocess. Including `--interactive` will set
79+
up an environment for that subprocess that allows interactivity, e.g., to take
80+
screenshots. The test ends once the dialog is dismissed.
81+
82+
The `FooDialogTest.InvokeDialog_default` test case **will still be run in the
83+
usual browser_tests test suite**. Ensure it passes, and isn’t flaky. This will
84+
give your dialog some regression test coverage. `RunDialog()` checks to ensure a
85+
dialog is actually created when it invokes `ShowDialog("default")`.
86+
87+
### BrowserDialogTest.Invoke
88+
89+
This is also run in browser_tests but, when run that way, the test case just
90+
lists the registered test harnesses (it does *not* iterate over them). A
91+
subprocess is never created unless --dialog is passed on the command line.
92+
93+
## Advanced Usage
94+
95+
If your test harness inherits from a descendant of `InProcessBrowserTest` (one
96+
example: [ExtensionBrowserTest]) then the `SupportsTestDialog<>` template is
97+
provided. E.g.
98+
99+
```cpp
100+
class ExtensionInstallDialogViewTestBase : public ExtensionBrowserTest { ...
101+
```
102+
103+
becomes
104+
105+
```cpp
106+
class ExtensionInstallDialogViewTestBase :
107+
public SupportsTestDialog<ExtensionBrowserTest> { ...
108+
```
109+
110+
### Testing additional dialog "styles"
111+
112+
Add additional test cases, with a different string after "`InvokeDialog_`".
113+
Example:
114+
115+
```cpp
116+
IN_PROC_BROWSER_TEST_F(CardUnmaskViewBrowserTest, InvokeDialog_expired) {
117+
RunDialog();
118+
}
119+
120+
IN_PROC_BROWSER_TEST_F(CardUnmaskViewBrowserTest, InvokeDialog_valid) {
121+
RunDialog();
122+
}
123+
```
124+
125+
The strings "`expired`" or “`valid`” will be given as arguments to
126+
`ShowDialog(std::string)`.
127+
128+
## Rationale
129+
130+
Bug reference: [Issue 654151](http://crbug.com/654151).
131+
132+
Chrome has a lot of browser dialogs; often for obscure use-cases and often hard
133+
to invoke. It has traditionally been difficult to be systematic while checking
134+
dialogs for possible regressions. For example, to investigate changes to shared
135+
layout parameters which are testable only with visual inspection.
136+
137+
For Chrome UI review, screenshots need to be taken. Iterating over all the
138+
"styles" that a dialog may appear with is fiddly. E.g. a login or particular web
139+
server setup may be required. It’s important to provide a consistent “look” for
140+
UI review (e.g. same test data, same browser size, anchoring position, etc.).
141+
142+
Some dialogs lack tests. Some dialogs have zero coverage on the bots. Dialogs
143+
can have tricky lifetimes and common mistakes are repeated. TestBrowserDialog
144+
runs simple "Show dialog" regression tests and can be extended to do more.
145+
146+
Even discovering the full set of dialogs present for each platform in Chrome is
147+
[difficult](http://crbug.com/686239).
148+
149+
### Why browser_tests?
150+
151+
* `browser_tests` already provides a `browser()->window()` of a consistent
152+
size that can be used as a dialog anchor and to take screenshots for UI
153+
review.
154+
* UI review have requested that screenshots be provided with the entire
155+
browser window so that the relative size of the dialog/change under
156+
review can be assessed.
157+
158+
* Some dialogs already have a test harness with appropriate setup (e.g. test
159+
data) running in browser_tests.
160+
* Supporting `BrowserDialogTest` should require minimal setup and minimal
161+
ongoing maintenance.
162+
163+
* An alternative is to maintain a working end-to-end build target executable
164+
to do this, but this has additional costs (and is hard).
165+
* E.g. setup/teardown of low-level functions (
166+
`InitializeGLOneOffPlatform()`,
167+
`MaterialDesignController::Initialize()`, etc.).
168+
169+
* Why not chrome.exe?
170+
* E.g. a scrappy chrome:// page with links to invoke dialogs would be
171+
great!
172+
* But...
173+
* A dialog may have test data (e.g. credit card info) which shouldn’t
174+
be in the release build.
175+
* A dialog may use EmbeddedTestServer.
176+
* Higher maintenance cost - can’t leverage existing test harnesses.
177+
178+
## Future Work
179+
180+
* Opt in more dialogs!
181+
* Eventually, all of them.
182+
* A `BrowserDialogTest` for every descendant of `views::DialogDelegate`.
183+
184+
* Automatically generate screenshots (for each platform, in various languages)
185+
* Build upon [CL 2008283002](https://codereview.chromium.org/2008283002/)
186+
187+
* (maybe) Try removing the subprocess
188+
* Probably requires altering the browser_test suite code directly rather
189+
than just adding a test case as in the current approach
190+
191+
* An automated test suite for dialogs
192+
* Test various ways to dismiss or hide a dialog
193+
* e.g. native close (via taskbar?)
194+
* close parent window (possibly via task bar)
195+
* close parent tab
196+
* switch tabs
197+
* close via `DialogClientView::AcceptWindow` (and `CancelWindow`)
198+
* close via `Widget::Close`
199+
* close via `Widget::CloseNow`
200+
* Drag tab off browser into a new window
201+
* Fullscreen that may create a new window/parent
202+
203+
* Find obscure workflows for invoking dialogs that have no test coverage and
204+
cause crashes (e.g. [http://crrev.com/426302](http://crrev.com/426302))
205+
* Supporting window-modal dialogs with a null parent window.
206+
207+
* Find memory leaks, e.g. [http://crrev.com/432320](http://crrev.com/432320)
208+
* "Fix memory leak for extension uninstall dialog".
209+
210+
## Appendix: Sample output
211+
212+
**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke**
213+
```
214+
Note: Google Test filter = BrowserDialogTest.Invoke
215+
[==========] Running 1 test from 1 test case.
216+
[----------] Global test environment set-up.
217+
[----------] 1 test from BrowserDialogTest
218+
[ RUN ] BrowserDialogTest.Invoke
219+
[26879:775:0207/134949.118352:30434675...:INFO:browser_dialog_browsertest.cc(46)
220+
Pass one of the following after --dialog=
221+
AskGoogleForSuggestionsDialogTest.InvokeDialog_default
222+
CardUnmaskPromptViewBrowserTest.InvokeDialog_expired
223+
CardUnmaskPromptViewBrowserTest.InvokeDialog_valid
224+
CollectedCookiesTestMd.InvokeDialog_default
225+
UpdateRecommendedDialogTest.InvokeDialog_default
226+
/* lots more will eventually be listed here */
227+
[ OK ] BrowserDialogTest.Invoke (0 ms)
228+
[----------] 1 test from BrowserDialogTest (0 ms total)
229+
[----------] Global test environment tear-down
230+
[==========] 1 test from 1 test case ran. (1 ms total)
231+
[ PASSED ] 1 test.
232+
[1/1] BrowserDialogTest.Invoke (334 ms)
233+
SUCCESS: all tests passed.
234+
```
235+
236+
**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke
237+
--dialog=CardUnmaskPromptViewBrowserTest.InvokeDialog_expired**
238+
239+
```
240+
Note: Google Test filter = BrowserDialogTest.Invoke
241+
[==========] Running 1 test from 1 test case.
242+
[----------] Global test environment set-up.
243+
[----------] 1 test from BrowserDialogTest
244+
[ RUN ] BrowserDialogTest.Invoke
245+
Note: Google Test filter = CardUnmaskPromptViewBrowserTest.InvokeDefault
246+
[==========] Running 1 test from 1 test case.
247+
[----------] Global test environment set-up.
248+
[----------] 1 test from CardUnmaskPromptViewBrowserTest, where TypeParam =
249+
[ RUN ] CardUnmaskPromptViewBrowserTest.InvokeDialog_expired
250+
/* 7 lines of uninteresting log spam */
251+
[ OK ] CardUnmaskPromptViewBrowserTest.InvokeDialog_expired (1324 ms)
252+
[----------] 1 test from CardUnmaskPromptViewBrowserTest (1324 ms total)
253+
[----------] Global test environment tear-down
254+
[==========] 1 test from 1 test case ran. (1325 ms total)
255+
[ PASSED ] 1 test.
256+
[ OK ] BrowserDialogTest.Invoke (1642 ms)
257+
[----------] 1 test from BrowserDialogTest (1642 ms total)
258+
[----------] Global test environment tear-down
259+
[==========] 1 test from 1 test case ran. (1642 ms total)
260+
[ PASSED ] 1 test.
261+
[1/1] BrowserDialogTest.Invoke (2111 ms)
262+
SUCCESS: all tests passed.
263+
```
264+
265+
**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke
266+
--dialog=CardUnmaskPromptViewBrowserTest.InvokeDialog_expired --interactive**
267+
```
268+
/*
269+
* Output as above, except the test are not interleaved, and the browser window
270+
* should remain open until the dialog is dismissed
271+
*/
272+
```
273+
274+
[chrome/browser/ui/test/test_browser_dialog.h]: https://cs.chromium.org/chromium/src/chrome/browser/ui/test/test_browser_dialog.h
275+
[chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc?l=104&q=ShowDialog
276+
[chrome/browser/ui/collected_cookies_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/collected_cookies_browsertest.cc?l=26&q=ShowDialog
277+
[chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc?l=18&q=ShowDialog
278+
[chrome/browser/ui/update_chrome_dialog_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/update_chrome_dialog_browsertest.cc?l=15&q=ShowDialog
279+
[ExtensionBrowserTest]: https://cs.chromium.org/chromium/src/chrome/browser/extensions/extension_browsertest.h?q=extensionbrowsertest&l=40

0 commit comments

Comments
 (0)