Bokeh is a large, multi-language project, and relies on varied and extensive tests and testing tools in order to maintain capability and prevent regressions. This chapter describes how to run various tests locally in a development environment, guidelines for writing tests, and information regarding the continuous testing infrastructure.
Running Tests Locally
Test Selection
Code Coverage
Other Options
Examples tests
Integration tests
Writing Tests
Python Unit Tests
JavaScript Unit Tests
Integration Tests
Continuous Integration
Configuration
Build Stages
Etiquette
Before attempting to run Bokeh tests, make sure you have successfully run through all of the instructions in the Getting Set Up section of the Developer’s Guide.
Additionally, on some platforms you may need to increase the maximum number of open file descriptors as some tests open many files to test the server.
ulimit -n 1024
To run all the basic python unit tests, run the following command at the top level of the repository:
py.test -m unit
Note that this includes unit tests that require Selenium to be installed. To exclude those unit tests, you can run the command:
py.test -m "unit and not selenium"
To run just the BokehJS unit tests, execute:
py.test -m js
Alternatively, you can also navigate to the bokehjs subdirectory of the source checkout and execute:
node make test
You can run all available tests (python and JS unit tests, as well as example and integration tests) from the top level directory by executing:
py.test
To learn more about marking test functions and selecting/deselecting them for a run, please consult the pytest documentation for custom markers. The list of currently defined test markers is below:
codebase: a test for codebase quality or policy
codebase
examples: an examples image-diff test
examples
integration: an integration test
integration
js: a javascript test
js
sampledata: a test for bokeh.sampledata
sampledata
bokeh.sampledata
selenium: a test requiring selenium
selenium
unit: a python unit test
unit
To run any of the tests with coverage use the following:
py.test --cov=bokeh
To report on a subset of the Bokeh package, pass e.g. -cov=bokeh/models.
-cov=bokeh/models
To run any of the tests without standard output captured use:
py.test -s
See the pytest documentation for further information on py.test and its options.
The examples tests run a selection of the Bokeh examples and generate images to compare against previous releases. A report is generated that displays the current and previous images, as well as any image difference.
Note
The tests do not currently fail if the images are different, the test report must be inspected manually.
To run just the examples tests, run the command:
py.test -m examples --report-path=examples.html
After the tests have run, you will be able to see the test report at examples.html. Running locally, you can name the test report whatever you want. On TravisCI, the examples report is always examples.html.
examples.html
The examples tests can run slowly, to speed them up, you can parallelize them:
py.test -m examples --report-path=examples.html -n 5
Where n is the number is the number of cores you want to use.
n
In addition, the examples tests generate a log file, examples.log which you can view at examples.log in the same directory that you the tests were run from.
examples.log
Warning
Server examples do get run, but phantomJS cannot currently capture the output, so they are always blank in the test results
In order to help keep Bokeh maintainable, all Pull Requests that touch code should normally be accompanied by relevant tests. While exceptions may be made for specific circumstances, the default assumption should be that a Pull Request without tests may not be merged.
Python unit tests maintain the basic functionality of the Python portion of the Bokeh library. A few general guidelines will help you write Python unit tests:
In order to ensure that Bokeh’s unit tests as relocatable and unambiguous as possible, always prefer absolute imports in test files. When convenient, import and use the entire module under test:
GOOD: import bokeh.models.transforms as bmt
import bokeh.models.transforms as bmt
GOOD: from bokeh.embed import components
from bokeh.embed import components
BAD: from ..document import Document
from ..document import Document
By default any unmarked test is considered part of the unit group. If a unit test needs an additional mark (e.g. selenium) then the unit marker must be supplied explicitly:
@pytest.mark.unit @pytest.mark.selenium def test_basic_script(capsys): # test code here
All new tests should use and assume pytest for test running, fixtures, parameterized testing, etc. New tests should not use the unittest module of the Python standard library.
unittest
These tests maintain the functionality of the BokehJS portion of the Bokeh project. The BokehJS tests are located in bokehjs/test. They are written using Chai “expect” style. If new test files are added, an appropriate entry in the directory index file should be added.
index
To add a new screen shot integration test, first make sure you can run existing screen shot tests, for example tests/integration/annotations/test_whisker.py. New screen shot tests should follow the general guidelines:
Be as simple as possible (only include things under test and nothing extra)
Prefer the bokeh.models API
bokeh.models
Once a new test is written, a base image for comparison is needed. To create a new base image, add --set-new-base-screenshot to your the standard py.test command to run the test. This will generate an image with the name base__<name_of_your_test>.png in the appropriate directory. Use git to check this image into the repository, and then all future screen shot tests will be compared against this base image.
--set-new-base-screenshot
base__<name_of_your_test>.png
git
Every push to the master branch or any Pull Request branch on GitHub automatically triggers a full test build on the TravisCI continuous integration service. This is most often useful for running the full Bokeh test suite continuously, but also triggers automated scripts for publishing releases when a tagged branch is pushed.
You can see the list of all current and previous builds at this URL: https://travis-ci.org/bokeh/bokeh
From there you can navigate to the build page for any specific build (e.g. for the latest merge to master, or a particular Pull Request). A typical build page looks like the image below:
As seen, the status of all build stages and jobs can be quickly inspected. When everything is running smoothly, all jobs will have a green check mark.
There are a number of files that affect the build configuration:
Defines the build matrix and global configurations for the stages described below.
Instructions for building a conda noarch package for Bokeh. This file is the single source of truth for build and test (but not runtime) dependencies.
Used to build sdist packages and “dev” installs. This file is also the single source of truth for runtime dependencies.
Contains some global configuration for build and test tools such as versioneer and pytest.
versioneer
pytest
The Build stage has a single job that is responsible for creating a noarch conda package for Bokeh. This ensures both that the BokehJS can be built correctly, and that important release packaging machinery is always functional. Additionally artifacts from this build, such as the conda package, and the BokehJS build directory, are saved to be re-used by future jobs, speeding up the entire build.
Build
noarch
The controlling script is scripts/ci/build
The Test stage is comprised of several jobs that run all the various Bokeh tests.
Test
The controlling script is scripts/ci/test, which calls a separate test:<GROUP> script for each of the following test groups:
test:<GROUP>
This job executes a large portion of the Bokeh examples to ensure that they run without any Python or JavaScript errors. Additionally, the job for PYTHON=2.7 generates images for the examples and a report that compares the images to previous versions.
PYTHON=2.7
This job executes an integration test, e.g. a Selenium browser test.
This job runs all the JavaScript unit tests (i.e. node make test)
This job runs all the Python unit tests (i.e. py.test -m unit). The tests are run on different jobs for Python versions 2.7 and 3.5+.
docs
This job runs the documentation build. For more information about building or contributing documentation see the Documentation section of the Developer’s guide.
This job runs tests that maintain code quality and package integrity.
The Deploy stage has a single job that is responsible for executing all the work necessary to complete a Bokeh release. This includes tasks such as:
Deploy
Building and publishing conda and sdist packages
Making BokehJS assets available on CDN
Building and deploying the Bokeh documentation site
Generating and uploading Bokeh examples tarballs
Publishing BokehJS NPM packages
All of these steps are performed for full releases, however some may be omitted for dev builds and release candidates.
The controlling script is scripts/ci/deploy
TravisCI provides five free build workers to Open Source projects. A few considerations will help you be considerate of others needing these limited resources:
Group commits into meaningful chunks of work before pushing to GitHub (i.e. don’t push on every commit).
If you must make multiple commits in succession, navigate to TravisCI and cancel all but the last build, in order to free up build workers.
If expensive examples tests are not needed (e.g. for a docs-only Pull Request), they may be disabled by adding the text
[ci disable examples]
to your commit message.