Propose a suite of declarative http api tests
To improve testing of the various aspects of the HTTP API, both in terms of coverage and readability, a suite of readable declarative tests is proposed. Change-Id: Id7a62f81368794624a89a6c33efd37c6a529548f
This commit is contained in:
parent
077692678d
commit
a7c5c623ab
287
specs/kilo/declarative-http-tests.rst
Normal file
287
specs/kilo/declarative-http-tests.rst
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
..
|
||||||
|
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||||
|
License.
|
||||||
|
|
||||||
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||||
|
|
||||||
|
==========================
|
||||||
|
Declarative HTTP API Tests
|
||||||
|
==========================
|
||||||
|
|
||||||
|
https://blueprints.launchpad.net/ceilometer/+spec/declarative-http-tests
|
||||||
|
|
||||||
|
This spec proposes a suite of "grey-box" tests for the Ceilometer HTTP
|
||||||
|
API that are driven by one or several human-readable text files that
|
||||||
|
declare URL requests alongside expected responses. These tests will
|
||||||
|
provide end to end tests of API endpoints that in addition to confirming
|
||||||
|
the functionality of the API will provide a cogent and readable overview
|
||||||
|
of the HTTP API.
|
||||||
|
|
||||||
|
The suite of tests augments rather than replaces existing tests
|
||||||
|
presuming that several small tools, each doing a focused job, are more
|
||||||
|
effective than one job doing everything. In this case the balance of the
|
||||||
|
focus is on traversing the breadth of the HTTP API to confirm it is in
|
||||||
|
rude health and demonstrating expected behaviors, not validation of data
|
||||||
|
provided by the API (unit tests ought to do that).
|
||||||
|
|
||||||
|
Transparency over the API ought to lead to better testing and
|
||||||
|
ultimately better APIs.
|
||||||
|
|
||||||
|
Problem description
|
||||||
|
===================
|
||||||
|
|
||||||
|
Existing Ceilometer `HTTP API`_ unit tests are enshrouded by and
|
||||||
|
encumbered with Python code and traditional unit test infrastructure.
|
||||||
|
These amount to noise when the purpose of a test is both to test *and*
|
||||||
|
to make visible the testing of the HTTP API. What should be most visible
|
||||||
|
is HTTP and the API. When these things are not visible, the
|
||||||
|
effectiveness of the tests as tools for discovery by a developer who
|
||||||
|
needs to make changes is limited.
|
||||||
|
|
||||||
|
The integration testing harness, `Tempest`_, suffers from some of
|
||||||
|
the same problems as above while also undergoing a refinement in purpose.
|
||||||
|
Rather than testing *all* the things, the future Tempest will evolve
|
||||||
|
to efficiently test the integration of *most* things. In this future
|
||||||
|
projects which wish to affirm their systems in detail will need to
|
||||||
|
do that testing themselves.
|
||||||
|
|
||||||
|
Tempest also more strictly requires that testcases have no knowledge
|
||||||
|
of the internals. This proposal would be free of such
|
||||||
|
constraints, which may prove convenient for test setup mechanics.
|
||||||
|
|
||||||
|
In addition, Tempest is now "branchless", so that the same test
|
||||||
|
branch is run against stable/{icehouse|juno} and master. This
|
||||||
|
requires that tests for newly testable features either discover the
|
||||||
|
availability of such features dynamically, or are explicitly
|
||||||
|
configured to be skipped depending on the branch Tempest is being
|
||||||
|
run against (neither option being ideal). This proposal would be free of
|
||||||
|
such complications, as the tests would live in-tree and thus be branched
|
||||||
|
in the same way as the rest of the codebase.
|
||||||
|
|
||||||
|
.. _HTTP API: https://github.com/openstack/ceilometer/tree/master/ceilometer/tests/api
|
||||||
|
.. _Tempest: https://github.com/openstack/tempest
|
||||||
|
|
||||||
|
Proposed change
|
||||||
|
===============
|
||||||
|
|
||||||
|
To address the shortcomings in HTTP testing (readability and
|
||||||
|
completeness) a new target for ``tox`` will be defined that runs a
|
||||||
|
suite of HTTP tests which are expressed as HTTP requests with
|
||||||
|
expected responses. The exact format should be determined from
|
||||||
|
discussion as these sorts of things always cause a lot of
|
||||||
|
contention. Best to get that out of the way early.
|
||||||
|
|
||||||
|
This same suite of tests will also be registered as a check job to
|
||||||
|
be run against patches proposed to the code review process.
|
||||||
|
|
||||||
|
In the ideal form the tests will run all the usual HTTP methods
|
||||||
|
against every URL made available by all the active endpoints
|
||||||
|
presented over HTTP by Ceilometer. This means that it should cover
|
||||||
|
both the pending v3 API that will be presented by Gnocchi as well as
|
||||||
|
the soon to deprecated older APIs.
|
||||||
|
|
||||||
|
To ensure the tests are lightweight and fast no web server will be used
|
||||||
|
and only one of whichever lightweight datastore (mongo, sqlite3) for
|
||||||
|
limited persistence. These tests are for testing the HTTP API aspect of
|
||||||
|
Ceilometer and as such are not scenario tests: We don't need to run
|
||||||
|
these tests against every available datastore.
|
||||||
|
|
||||||
|
"No web server" can be achieved by using `wsgi-intercept`_,
|
||||||
|
`WebTest`_ or similar. The choice of tool should be driven by
|
||||||
|
determining which is best able to facilitate easy translation from
|
||||||
|
the declarative format to tests that can be handled by the runner.
|
||||||
|
|
||||||
|
The declarative format of the tests need to balance between easy for
|
||||||
|
a human to write and read and easy for a computer to parse. There
|
||||||
|
are two general classes of style:
|
||||||
|
|
||||||
|
* Something that looks a bit like the output of ``curl -v``. This
|
||||||
|
has the advantage of looking just like HTTP on the wire but the
|
||||||
|
disadvantage that it is hard to express partial expectations or
|
||||||
|
partial requests.
|
||||||
|
|
||||||
|
* A list of dictionaries that represent requests and expected
|
||||||
|
responses. This is easy to express in a common format like
|
||||||
|
YAML, can deal with partial information well, and handle a form of
|
||||||
|
inheritance. The author has some `good success`_ with this format
|
||||||
|
so tends to prefer it.
|
||||||
|
|
||||||
|
Assuming the latter format a possible implementation would include:
|
||||||
|
|
||||||
|
* A test runner that parses YAML files to generate tests which will
|
||||||
|
be captured by the testing harness. This runner, besides making
|
||||||
|
the HTTP requests and processing responses, will be responsible
|
||||||
|
for setup: establishing the necessary services and other
|
||||||
|
prerequisites of the tests.
|
||||||
|
|
||||||
|
* A directory including multiple YAML files each representing a
|
||||||
|
transaction/scenario of some kind in the API *or* all the routes
|
||||||
|
in one version of the API.
|
||||||
|
|
||||||
|
Note that this proposal makes no mention of client code because it is
|
||||||
|
direct HTTP requests that are being tested, not calls to a client
|
||||||
|
library. This is entirely the point: a client library hides HTTP and
|
||||||
|
what we are trying to do here is expose HTTP interactions to the harsh
|
||||||
|
light of review.
|
||||||
|
|
||||||
|
There are a few questions which will need to be resolved to reach a
|
||||||
|
complete solution. It should be possible to resolve these in flight.
|
||||||
|
The questions include:
|
||||||
|
|
||||||
|
* What format for the tests?
|
||||||
|
* How to handle authN and authZ in a minimal fashion? Ideally keystone
|
||||||
|
won't be running. If that's the case, what needs to be done?
|
||||||
|
* How to aggregate request and response groups into single tests?
|
||||||
|
One option is for each YAML file to be treated as a single test.
|
||||||
|
|
||||||
|
.. _wsgi-intercept: https://pypi.python.org/pypi/wsgi_intercept
|
||||||
|
.. _WebTest: http://webtest.readthedocs.org/
|
||||||
|
.. _good success: https://github.com/tiddlyweb/tiddlyweb/blob/master/test/httptest.yaml
|
||||||
|
|
||||||
|
Alternatives
|
||||||
|
------------
|
||||||
|
|
||||||
|
There are several alternative options to a standalone suite of
|
||||||
|
declarative HTTP tests within the Ceilometer code tree:
|
||||||
|
|
||||||
|
* Propose a spec `to qa`_ for building a general purpose solution to
|
||||||
|
the problem of declarative HTTP tests in-tree. Long term this
|
||||||
|
would be a great outcome, but this outcome seems more likely if
|
||||||
|
people are able to see a working version against which
|
||||||
|
improvements can be made.
|
||||||
|
|
||||||
|
* Don't use a standalone suite, have the tests integrated with a
|
||||||
|
larger set of in-tree functional and/or integration tests. While
|
||||||
|
this may be a good idea from a management of complexity standpoint
|
||||||
|
it has limited value in ensuring the tight focus of purpose that
|
||||||
|
is required for something to be good at its purpose.
|
||||||
|
|
||||||
|
* Don't use declarative tests, instead continue with
|
||||||
|
object-oriented ``unittests`` style that is the norm throughout many
|
||||||
|
tests. Doing this will defeat the purpose of the proposal (exposing
|
||||||
|
and expressing HTTP) so is not recommended.
|
||||||
|
|
||||||
|
* Run the tests against various storage and web server scenarios to
|
||||||
|
achieve maximum coverage across a variety of situations. While
|
||||||
|
this may have value, it would lead to slow tests and increase
|
||||||
|
complexity of the harness significantly. Slow tests discourage people
|
||||||
|
running them and complexity leads to breakage.
|
||||||
|
|
||||||
|
* Do nothing. Use existing unit tests and tempests test. This is
|
||||||
|
not a good option as neither the existing unit tests nor Tempest tests
|
||||||
|
present good (and readable) coverage.
|
||||||
|
|
||||||
|
.. _to qa: https://github.com/openstack/qa-specs
|
||||||
|
|
||||||
|
Data model impact
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
None. The data model should be invisible to these tests.
|
||||||
|
|
||||||
|
REST API impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
These tests will not add to the API, but with luck will improve it.
|
||||||
|
|
||||||
|
Security impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Pipeline impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Other end user impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Writing and running these tests may demonstrate that the API is
|
||||||
|
confusing and hard to use which may then lead to making it better.
|
||||||
|
This would be awesome.
|
||||||
|
|
||||||
|
Performance/Scalability Impacts
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The additional gate check job may have some impact on performance there
|
||||||
|
but these changes are not expected to impact the performance of
|
||||||
|
Ceilometer itself.
|
||||||
|
|
||||||
|
Other deployer impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Developer impact
|
||||||
|
----------------
|
||||||
|
|
||||||
|
If a developer adds to or changes the HTTP API those changes will need
|
||||||
|
to reflected in this test suite.
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
|
Assignee(s)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Primary assignee:
|
||||||
|
chdent
|
||||||
|
|
||||||
|
Other contributors:
|
||||||
|
dbelova
|
||||||
|
|
||||||
|
Ongoing maintainer:
|
||||||
|
chdent
|
||||||
|
|
||||||
|
Work Items
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Decide on the declarative format.
|
||||||
|
* Determine extent or depth of testing (are web servers being used?
|
||||||
|
other data store?).
|
||||||
|
* Write harness.
|
||||||
|
* Write first round of tests.
|
||||||
|
* Integrate with tox and testr.
|
||||||
|
* Create gate job.
|
||||||
|
|
||||||
|
|
||||||
|
Future lifecycle
|
||||||
|
================
|
||||||
|
|
||||||
|
As features are added and removed to and from the API tests for
|
||||||
|
those features will need to be changed in this suite. Most of the
|
||||||
|
time that should be done by the implementor of the feature but there
|
||||||
|
will be times that larger cleanups are required.
|
||||||
|
|
||||||
|
Similarly if storage handling becomes a part of the test suite, then
|
||||||
|
as new storage systems are implemented (or removed), they will need
|
||||||
|
to be handled.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
This work is self contained but may add to the libraries required
|
||||||
|
for testing (e.g. wsgi-intercept).
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
As a suite of tests, this system will test itself. It should,
|
||||||
|
however, include some sanity tests within itself to make sure it is
|
||||||
|
behaving.
|
||||||
|
|
||||||
|
Documentation Impact
|
||||||
|
====================
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
See links above and:
|
||||||
|
|
||||||
|
* https://wiki.python.org/moin/PythonTestingToolsTaxonomy for prior
|
||||||
|
art and potential formats.
|
||||||
|
* http://lists.openstack.org/pipermail/openstack-dev/2014-October/049056.html
|
||||||
|
related mailing list thread.
|
Loading…
Reference in New Issue
Block a user