mirror of https://github.com/kivy/kivy.git
161 lines
4.8 KiB
ReStructuredText
161 lines
4.8 KiB
ReStructuredText
Unit tests
|
|
==========
|
|
|
|
Tests are located in the kivy/tests folder. If you find a bug in kivy, a good
|
|
thing to do can be to write a minimal case showing the issue and to ask core devs
|
|
if the behaviour shown is intended or a real bug. If you write your code as a
|
|
unittest, it will prevent the bug from coming back unnoticed in the future, and
|
|
will make Kivy a better, stronger project. Writing a unittest may be a really
|
|
good way to get familiar with Kivy while doing something useful.
|
|
|
|
Unit tests are seperated into two cases:
|
|
|
|
* Non graphics unit tests: theses are standard unit tests that can run in a console
|
|
* Graphics unit tests: theses need a GL context, and work via image comparison
|
|
|
|
To be able to run unit tests, you need to install nose
|
|
(http://code.google.com/p/python-nose/), and coverage
|
|
(http://nedbatchelder.com/code/coverage/). You can use easy_install for that::
|
|
|
|
sudo easy_install nose coverage
|
|
|
|
Then, in the kivy directory::
|
|
|
|
make test
|
|
|
|
How it works
|
|
------------
|
|
|
|
All the tests are located in `kivy/tests`, and the filename starts with
|
|
`test_<name>.py`. Nose will automatically gather all the files and classes
|
|
inside this folder, and use them to generate test cases.
|
|
|
|
To write a test, create a file that respects the previous naming, then
|
|
start with this template::
|
|
|
|
import unittest
|
|
|
|
class XXXTestCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
# import class and prepare everything here.
|
|
pass
|
|
|
|
def test_YYY(self):
|
|
# place your test case here
|
|
a = 1
|
|
self.assertEqual(a, 1)
|
|
|
|
Replace `XXX` with an appropriate name that covers your tests cases, then
|
|
replace 'YYY' by the name of your test. If you have some doubt, check how
|
|
the other files have been done.
|
|
|
|
Then, to execute them, just run::
|
|
|
|
make test
|
|
|
|
If you want to execute that file only, you can run::
|
|
|
|
nosetests kivy/tests/test_yourtestcase.py
|
|
|
|
|
|
GL unit tests
|
|
-------------
|
|
|
|
GL unit test are more difficult. You must know that even if OpenGL is a
|
|
standard, the output/rendering is not. It depends on your GPU and the driver
|
|
used. For theses tests, the goal is to save the output of the rendering at
|
|
frame X, and compare it to a reference image.
|
|
|
|
Currently, images are generated in 320x240, png.
|
|
|
|
.. note::
|
|
|
|
Currently, image comparison is done per-pixel. This means the reference
|
|
image that you generate will only be correct for your GPU/driver. If
|
|
somebody can implement image comparison with "delta" support, patches
|
|
are welcome :)
|
|
|
|
To execute gl unit test, you need to create a directory::
|
|
|
|
mkdir kivy/tests/results
|
|
make test
|
|
|
|
The results directory will contain all the reference images, and the
|
|
generated images. After the first execution, if the results directory is empty,
|
|
no comparison will be done. It will use the generated images as reference.
|
|
After the second execution, all the images will be compared to the reference
|
|
images.
|
|
|
|
A html file is available to show the comparison before/after the test, and a
|
|
snippet of the associated unit test. It will be generated at:
|
|
|
|
kivy/tests/build/index.html
|
|
|
|
.. note::
|
|
|
|
The build directory is cleaned after each call to `make test`. If you don't
|
|
want that, just use nosetests command.
|
|
|
|
Writing GL Unit tests
|
|
---------------------
|
|
|
|
The idea is to create a root widget, as you would do in
|
|
:meth:`~kivy.app.App.build()`, or for :func:`kivy.base.runTouchApp()`.
|
|
You'll give that root widget to a rendering function, that will capture the
|
|
output in X frames.
|
|
|
|
Here is an example::
|
|
|
|
from common import GraphicUnitTest
|
|
|
|
class VertexInstructionTestCase(GraphicUnitTest):
|
|
|
|
def test_ellipse(self):
|
|
from kivy.uix.widget import Widget
|
|
from kivy.graphics import Ellipse, Color
|
|
r = self.render
|
|
|
|
# create a root widget
|
|
wid = Widget()
|
|
|
|
# put some graphics instruction on it
|
|
with wid.canvas:
|
|
Color(1, 1, 1)
|
|
self.e = Ellipse(pos=(100, 100), size=(200, 100))
|
|
|
|
# render, and capture it directly
|
|
r(wid)
|
|
|
|
# as alternative, you can capture in 2 frames:
|
|
r(wid, 2)
|
|
|
|
# or in 10 frames
|
|
r(wid, 10)
|
|
|
|
Each call to `self.render` (or `r` in our example) will generate an image named
|
|
like this::
|
|
|
|
<classname>_<funcname>-<r-call-count>.png
|
|
|
|
`r-call-count` represents the number of times that `self.render` is called inside
|
|
the test function.
|
|
|
|
The reference images are named::
|
|
|
|
ref_<classname>_<funcname>-<r-call-count>.png
|
|
|
|
You can replace the reference image with a new one easily.
|
|
|
|
|
|
Coverage reports
|
|
----------------
|
|
|
|
Coverage is based on the execution of the previous tests. Statistics on code
|
|
coverage are automatically grabbed during execution. You can generate an html
|
|
report of the coverage with the command::
|
|
|
|
make cover
|
|
|
|
Then, open `kivy/htmlcov/index.html` with your favorite web browser.
|