Run tools/test
to run all our test suites. This command is
typically quite fast (5-10s, sometimes less), because it only rechecks
tests related to the files you've changed.
You can run all our tests with tools/test --all
. We run them this
way in our CI, e.g. when you send a PR.
To see all options, run tools/test --help
.
tools/test jest
runs our JS unit tests. These are written using
Jest.
To write a test, place a Javascript file with the -test.js
suffix in the
__tests__
directory inside of any subfolder of /src
. The test will be
automatically picked up by the test runner.
The bulk of our JS code runs the same way on both iOS and Android, but
some of it conditions on the platform. By default, tools/test
runs
our Jest tests just once, picking the platform arbitrarily, to avoid
taking twice as long. (See
architecture/testing.md
for more discussion.) If you're testing code that does depend on the
platform, use the --all
or --platform
option (see tools/test --help
for details) to be sure to exercise the case of the relevant platform,
or both of them.
-
New test files should be
@flow strict-local
, just like all our non-test code. -
Tests should use the
exampleData
module as needed to produce objects of typeUser
,Message
,GlobalState
, and our many other data types.-
This typically allows a test to write out only the details relevant to it -- far less tedious than writing out lots of other properties that the application code expects to exist, but the given test doesn't care about the specific value of.
-
If
exampleData
doesn't already have code to produce the type you need, add to it.
-
-
Lots of existing tests aren't marked with
@flow
. If making substantial changes to a test file, first bring it up to our normal typing standards: add@flow strict-local
and make it pass Flow.-
Most of these tests build example data by hand, and to stay at a bearable level of tedium they leave out a lot of properties the real non-test objects would have, causing type errors.
To convert such code to well-typed code, you'll want to use
exampleData
as described above.
-
-
Use deepFreeze to test functions which access redux state. This won't allow the object to be mutated and hence will eventually fail tests in case of mutation.
We have a small, nascent suite of unit tests for our Android-native (Kotlin and Java) code.
tools/test native
runs this suite, as well as building all the
Android code.
Tests are written in Kotlin, using JUnit 4 and the Truth library. If you're writing Android unit tests:
- Definitely read the short Android guide on principles of testing -- it's a good writeup.
- Definitely also read the short Android guide on local unit tests,
which has more concrete details about the APIs we use here.
- (A "local unit test" is Android jargon for a genuine, self-contained unit test, specifically a test that doesn't require an Android device to run on. All our unit tests are "local unit tests".)
Other sources which might be helpful to read or refer to:
- Truth docs: homepage, FAQ
- JUnit docs: e.g. Assertions javadoc, user guide
- Good blog-style articles from "Baeldung": on JUnit in Kotlin and on Truth.
We don't yet have native-code tests for iOS. We should try it out! A good incremental step will be to at least check that the build completes without errors.
Functional tests have not been set up. We plan to use Appium.
We use ESLint to catch many kinds of style issues, together with Prettier to maintain consistent formatting.
Our lint config starts from the Airbnb guides (for ES6 and for React), with a number of specific changes.
Prettier is an "opinionated" tool, which is a euphemism for having virtually no configuration options; and unfortunately a few of its unchangeable "opinions" are outright harmful. So we use prettier-eslint to overrule it on those points; the details are in a small, formatting-only ESLint config file.
For proper results, always run ESLint or Prettier through our canonical interfaces:
tools/test
(ortools/test lint prettier
for these steps alone);tools/test --fix
, to actually modify the files to fix issues where possible; or- in your editor, with our recommended editor config.
If you find another interface more convenient, please send a PR and/or mention it in chat! We'll be interested to learn about it, and to see what we can do to support it.
We use the Flow type-checker on our JS code, and flow-typed for community-maintained type definitions for many dependencies.
Flow is not among the world's best-documented software. If you don't find something in its docs, it's worth
- searching its issues (including closed issues); sometimes a valuable feature is undocumented and the best discussion of it is where someone offers it as a workaround in an issue thread.
- scanning this "cheat sheet" maintained by another Flow user, which provides an index of features both documented and undocumented.