Skip to content

Commit 4112f5e

Browse files
committed
[lldb][NFC] Specify guidelines for API tests
This patch specifies a few guidelines that our API tests should follow. The motivations for this are twofold: 1. API tests have unexpected pitfalls that especially new contributors run into when writing tests. To prevent the frustration of letting people figure those pitfalls out by trial-and-error, let's just document them briefly in one place. 2. It prevents some arguing about what is the right way to write tests. I really like to have fast and reliable API test suite, but I also don't want to be the bogeyman that has to insist in every review that the test should be rewritten to not launch a process for no good reason. It's much easier to just point to a policy document. I omitted some guidelines that I think could be controversial (e.g., the whole "should assert message describe failure or success"). Reviewed By: shafik Differential Revision: https://reviews.llvm.org/D101153
1 parent d3676d4 commit 4112f5e

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

lldb/docs/resources/test.rst

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,129 @@ program being debugged. The fact that the API tests work with different
196196
variants mean that more general tests should be API tests, so that they can be
197197
run against the different variants.
198198

199+
Guidelines for API tests
200+
^^^^^^^^^^^^^^^^^^^^^^^^
201+
202+
API tests are expected to be fast, reliable and maintainable. To achieve this
203+
goal, API tests should conform to the following guidelines in addition to normal
204+
good testing practices.
205+
206+
**Don't unnecessarily launch the test executable.**
207+
Launching a process and running to a breakpoint can often be the most
208+
expensive part of a test and should be avoided if possible. A large part
209+
of LLDB's functionality is available directly after creating an `SBTarget`
210+
of the test executable.
211+
212+
The part of the SB API that can be tested with just a target includes
213+
everything that represents information about the executable and its
214+
debug information (e.g., `SBTarget`, `SBModule`, `SBSymbolContext`,
215+
`SBFunction`, `SBInstruction`, `SBCompileUnit`, etc.). For test executables
216+
written in languages with a type system that is mostly defined at compile
217+
time (e.g., C and C++) there is also usually no process necessary to test
218+
the `SBType`-related parts of the API. With those languages it's also
219+
possible to test `SBValue` by running expressions with
220+
`SBTarget.EvaluateExpression` or the `expect_expr` testing utility.
221+
222+
Functionality that always requires a running process is everything that
223+
tests the `SBProcess`, `SBThread`, and `SBFrame` classes. The same is true
224+
for tests that exercise breakpoints, watchpoints and sanitizers.
225+
Languages such as Objective-C that have a dependency on a runtime
226+
environment also always require a running process.
227+
228+
**Don't unnecessarily include system headers in test sources.**
229+
Including external headers slows down the compilation of the test executable
230+
and it makes reproducing test failures on other operating systems or
231+
configurations harder.
232+
233+
**Avoid specifying test-specific compiler flags when including system headers.**
234+
If a test requires including a system header (e.g., a test for a libc++
235+
formatter includes a libc++ header), try to avoid specifying custom compiler
236+
flags if possible. Certain debug information formats such as ``gmodules``
237+
use a cache that is shared between all API tests and that contains
238+
precompiled system headers. If you add or remove a specific compiler flag
239+
in your test (e.g., adding ``-DFOO`` to the ``Makefile`` or ``self.build``
240+
arguments), then the test will not use the shared precompiled header cache
241+
and expensively recompile all system headers from scratch. If you depend on
242+
a specific compiler flag for the test, you can avoid this issue by either
243+
removing all system header includes or decorating the test function with
244+
``@no_debug_info_test`` (which will avoid running all debug information
245+
variants including ``gmodules``).
246+
247+
**Test programs should be kept simple.**
248+
Test executables should do the minimum amount of work to bring the process
249+
into the state that is required for the test. Simulating a 'real' program
250+
that actually tries to do some useful task rarely helps with catching bugs
251+
and makes the test much harder to debug and maintain. The test programs
252+
should always be deterministic (i.e., do not generate and check against
253+
random test values).
254+
255+
**Identifiers in tests should be simple and descriptive.**
256+
Often test programs need to declare functions and classes which require
257+
choosing some form of identifier for them. These identifiers should always
258+
either be kept simple for small tests (e.g., ``A``, ``B``, ...) or have some
259+
descriptive name (e.g., ``ClassWithTailPadding``, ``inlined_func``, ...).
260+
Never choose identifiers that are already used anywhere else in LLVM or
261+
other programs (e.g., don't name a class ``VirtualFileSystem``, a function
262+
``llvm_unreachable``, or a namespace ``rapidxml``) as this will mislead
263+
people ``grep``'ing the LLVM repository for those strings.
264+
265+
**Prefer LLDB testing utilities over directly working with the SB API.**
266+
The ``lldbutil`` module and the ``TestBase`` class come with a large amount
267+
of utility functions that can do common test setup tasks (e.g., starting a
268+
test executable and running the process to a breakpoint). Using these
269+
functions not only keeps the test shorter and free of duplicated code, but
270+
they also follow best test suite practices and usually give much clearer
271+
error messages if something goes wrong. The test utilities also contain
272+
custom asserts and checks that should be preferably used (e.g.
273+
``self.assertSuccess``).
274+
275+
**Prefer calling the SB API over checking command output.**
276+
Avoid writing your tests on top of ``self.expect(...)`` calls that check
277+
the output of LLDB commands and instead try calling into the SB API. Relying
278+
on LLDB commands makes changing (and improving) the output/syntax of
279+
commands harder and the resulting tests are often prone to accepting
280+
incorrect test results. Especially improved error messages that contain
281+
more information might cause these ``self.expect`` calls to unintentionally
282+
find the required ``substrs``. For example, the following ``self.expect``
283+
check will unexpectedly pass if it's ran as the first expression in a test:
284+
285+
::
286+
287+
self.expect("expr 2 + 2", substrs=["0"])
288+
289+
When running the same command in LLDB the reason for the unexpected success
290+
is that '0' is found in the name of the implicitly created result variable:
291+
292+
::
293+
294+
(lldb) expr 2 + 2
295+
(int) $0 = 4
296+
^ The '0' substring is found here.
297+
298+
A better way to write the test above would be using LLDB's testing function
299+
``expect_expr`` will only pass if the expression produces a value of 0:
300+
301+
::
302+
303+
self.expect_expr("2 + 2", result_value="0")
304+
305+
**Prefer using specific asserts over the generic assertTrue/assertFalse.**.
306+
The `self.assertTrue`/`self.assertFalse` functions should always be your
307+
last option as they give non-descriptive error messages. The test class has
308+
several expressive asserts such as `self.assertIn` that automatically
309+
generate an explanation how the received values differ from the expected
310+
ones. Check the documentation of Python's `unittest` module to see what
311+
asserts are available. If you can't find a specific assert that fits your
312+
needs and you fall back to a generic assert, make sure you put useful
313+
information into the assert's `msg` argument that helps explain the failure.
314+
315+
::
316+
317+
# Bad. Will print a generic error such as 'False is not True'.
318+
self.assertTrue(expected_string in list_of_results)
319+
# Good. Will print expected_string and the contents of list_of_results.
320+
self.assertIn(expected_string, list_of_results)
321+
199322
Running The Tests
200323
-----------------
201324

0 commit comments

Comments
 (0)