index.rst (10051B)
1 GTest 2 ===== 3 4 GTest (googletest) is Google's framework for writing C++ tests on a 5 variety of platforms (Linux, Mac OS X, Windows, ...). 6 Based on the xUnit architecture, it supports automatic test 7 discovery, a rich set of assertions, user-defined assertions, death 8 tests, fatal and non-fatal failures, value- and type-parameterized 9 tests, various options for running the tests, and XML test report 10 generation. 11 12 Integration 13 ----------- 14 15 GTest is run as a standard test task on Win/Mac/Linux and Android, under 16 treeherder symbol 'GTest'. 17 18 19 Running tests 20 ------------- 21 22 The Firefox build process will build GTest on supported platforms as 23 long as you don't disable tests in your mozconfig. However xul-gtest will 24 only be built when tests are required to save an expensive second 25 linking process. 26 27 To run the unit tests use 'mach gtest' when invoking Gecko. 28 29 Running selected tests 30 ~~~~~~~~~~~~~~~~~~~~~~ 31 32 Tests can be selected using mach. You can also use environment variables 33 support by GTest. See `Running Test Programs: Running a Subset of the 34 Tests <https://github.com/google/googletest/blob/master/docs/advanced.md#running-a-subset-of-the-tests>`__ 35 for more details. 36 37 :: 38 39 mach gtest Moz2D.* 40 41 42 Configuring GTest 43 ~~~~~~~~~~~~~~~~~ 44 45 GTest can be controlled from other environment variables. See `Running 46 Test Programs: Advanced 47 Options <https://github.com/google/googletest/blob/master/docs/advanced.md#running-test-programs-advanced-options>`__ 48 for more details. 49 50 51 Debugging a GTest Unit Test 52 --------------------------- 53 54 To debug a gtest, pass --debug to the normal command. 55 56 .. code-block:: shell 57 58 ./mach gtest --debug [ Prefix.Test ] 59 60 If that doesn't work, you can try running the firefox binary under the 61 debugger with the MOZ_RUN_GTEST environment variable set to 1. 62 63 .. code-block:: shell 64 65 MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb] 66 67 .. warning:: 68 69 Don't forget to build + run 'mach gtest' to relink when using 70 MOZ_RUN_GTEST since it's not part of a top level build. 71 72 Note that this will load an alternate libxul - the one which has the 73 test code built in, which resides in a gtest/subdirectory of your 74 objdir. This gtest-enabled libxul is not built as part of the regular 75 build, so you must ensure that it is built before running the above 76 command. A simple way to do this is to just run "mach gtest" which will 77 rebuild libxul and run the tests. You can also extract the commands 78 needed to just rebuild that libxul `from 79 mach <https://hg.mozilla.org/mozilla-central/file/3673d2c688b4/python/mozbuild/mozbuild/mach_commands.py#l486>`__ 80 and run those directly. Finally, note that you may have to run through 81 the tests once for gdb to load all the relevant libraries and for 82 breakpoint symbols to resolve properly. 83 84 Note that you can debug a subset of the tests (including a single test) 85 by using the GTEST_FILTER environment variable: 86 87 .. code-block:: shell 88 89 GTEST_FILTER='AsyncPanZoom*' MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb] 90 91 92 Debugging with Xcode 93 ~~~~~~~~~~~~~~~~~~~~ 94 95 See :ref:`Debugging On macOS` for initial 96 setup. You'll likely want to create a separate scheme for running GTest 97 ("Product" > "Scheme" > "New Scheme…"). In addition to GTEST_FILTER, Set 98 the following environment variables: 99 100 :: 101 102 MOZ_XRE_DIR=/path-to-object-directory/obj-ff-dbg/dist/bin 103 MOZ_RUN_GTEST=True 104 105 and under the "Options" tab for the scheme, set the working directory 106 to: 107 108 :: 109 110 ☑️ Use custom working directory: /path-to-object-directory/obj-ff-dbg/_tests/gtest 111 112 113 Debugging with Visual Studio Code 114 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 115 116 Add a configuration like this to your launch.json file (you can edit it 117 via Run / Open Configurations): 118 119 :: 120 121 { 122 "name": "(gdb) Launch gtest", 123 "type": "cppdbg", 124 "request": "launch", 125 "program": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/dist/bin/firefox", 126 "args": [], 127 "stopAtEntry": false, 128 "cwd": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/_tests/gtest", 129 "environment": [{"name": "MOZ_RUN_GTEST", "value": "True"}, 130 {"name": "GTEST_FILTER", "value": "AsyncPanZoom*"}], 131 "externalConsole": false, 132 "MIMode": "gdb", 133 "setupCommands": [ 134 { 135 "description": "Enable pretty-printing for gdb", 136 "text": "-enable-pretty-printing", 137 "ignoreFailures": true 138 } 139 ] 140 }, 141 142 143 Writing a GTest Unit Test 144 ------------------------- 145 146 Most of the `GTest 147 documentation <https://github.com/google/googletest/blob/master/googletest/README.md>`__ 148 will apply here. The `GTest 149 primer <https://github.com/google/googletest/blob/master/docs/primer.md>`__ 150 is a recommended read. 151 152 .. warning:: 153 154 GTest will run tests in parallel. Don't add unit tests that are not 155 threadsafe, such as tests that require focus or use specific sockets. 156 157 .. warning:: 158 159 GTest will run without initializing mozilla services. Initialize and 160 tear down any dependencies you have in your test fixtures. Avoid 161 writing integration tests and focus on testing individual units. 162 163 See https://hg.mozilla.org/mozilla-central/rev/ed612eec41a44867a for an 164 example of how to add a simple test. 165 166 If you're converting an existing C++ unit test to a GTest, `this 167 commit <https://hg.mozilla.org/mozilla-central/rev/40740cddc131>`__ may 168 serve as a useful reference. 169 170 171 Setting prefs for a test 172 ~~~~~~~~~~~~~~~~~~~~~~~~ 173 174 If tests cover functionality that is disabled by default, you'll have to 175 change the relevant preferences either in the individual test: 176 177 :: 178 179 bool oldPref = Preferences::GetBool(prefKey); 180 Preferences::SetBool(prefKey, true); 181 … // test code 182 Preferences::SetBool(prefKey, oldPref); 183 184 or, if it applies more broadly, the change can be applied to the whole 185 fixture (see `the GTest 186 docs <https://github.com/google/googletest/blob/master/googletest/README.md>`__, 187 or 188 `AutoInitializeImageLib <https://searchfox.org/mozilla-central/search?q=AutoInitializeImageLib%3A%3AAutoInitializeImageLib&path=>`__ 189 as an example). 190 191 192 Adding a test to the build system 193 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 195 Find a gtest directory appropriate for the module. If none exist create 196 a directory using the following convention: '<submodule>/tests/gtest'. 197 Create a moz.build file (in the newly created directory) with a module 198 declaration, replacing gfxtest with a unique name, and set 199 UNIFIED_SOURCES to contain all of the test file names. 200 201 What we're doing here is creating a list of source files that will be 202 compiled and linked only against the gtest version of libxul. This will 203 let these source files call internal xul symbols without making them 204 part of the binary we ship to users. 205 206 .. code-block:: 207 208 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- 209 # vim: set filetype=python: 210 # This Source Code Form is subject to the terms of the Mozilla Public 211 # License, v. 2.0. If a copy of the MPL was not distributed with this 212 # file, you can obtain one at https://mozilla.org/MPL/2.0/. 213 214 Library('gfxtest') 215 216 UNIFIED_SOURCES = [ 217 <ListTestFiles>, 218 ] 219 220 FINAL_LIBRARY = 'xul-gtest' 221 222 Update '<submodule>/moz.build' in the parent directory to build your new 223 subdirectory in: 224 225 .. code-block:: python 226 227 TEST_DIRS += [ 228 "gtest", 229 ] 230 231 When adding tests to an existing moz.build file (it has FINAL_LIBRARY = 232 'xul-gtest'), add the following. That's it--there is no test manifest 233 required. Your tests will be automatically registered using a static 234 constructor. 235 236 .. code-block:: python 237 238 UNIFIED_SOURCES = [ 239 'TestFoo.cpp', 240 ] 241 242 Notes 243 ~~~~~ 244 245 The include file for the class you are testing may not need to be 246 globally exported, but it does need to be made available to the unit 247 test you are writing. In that case, add something like this to the 248 Makefile.in inside of the testing directory. 249 250 .. code-block:: python 251 252 LOCAL_INCLUDES += [ 253 '/gfx/2d', 254 '/gfx/2d/unittest', 255 '/gfx/layers', 256 ] 257 258 Gtests currently run from the test package under the **GTest** symbol on 259 `Treeherder <https://treeherder.mozilla.org/>`__ if you want to verify 260 that your test is working. Formerly they were run under the **B** 261 symbol, during \`make check`. 262 263 264 MozGTestBench 265 ------------- 266 267 A Mozilla GTest Microbench is just a GTest that reports the test 268 duration to perfherder. It's an easy way to add low level performance 269 test. Keep in mind that there's a non-zero cost to monitoring 270 performance test so use them sparingly. You can still perform test 271 assertions. 272 273 274 Writing a Microbench GTest 275 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 276 277 Use 'MOZ_GTEST_BENCH' instead of 'TEST' to time the execution of your 278 test. Example: 279 280 .. code-block:: cpp 281 282 #include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH 283 284 ... 285 286 MOZ_GTEST_BENCH(GfxBench, TEST_NAME, []{ 287 // Test to time the execution 288 }); 289 290 Make sure this file is registered with the file system using the 291 instructions above. If everything worked correctly you should see this 292 in the GTest log for your corresponding test: 293 294 .. code-block:: js 295 296 PERFHERDER_DATA: {"framework": {"name": "platform_microbench"}, "suites": [{"name": "GfxBench", "subtests": [{"name": "CompositorSimpleTree", "value": 252674, "lowerIsBetter": true}]}]} 297 298 299 Sheriffing policy 300 ~~~~~~~~~~~~~~~~~ 301 302 Microbench tests measure the speed of a very specific operation. A 303 regression in a micro-benchmark may not lead to a user visible 304 regression and should not be treated as strictly as a Talos regression. 305 Large changes in microbench scores will also be expected when the code 306 is directly modified and should be accepted if the developer intended to 307 change that code. Micro-benchmarks however provide a framework for 308 adding performance tests for platform code and regression tests for 309 performance fixes. They will catch unintended regressions in code and 310 when correlated with a Talos regression might indicate the source of the 311 regression.