Development:Unit tests: Difference between revisions
Line 120: | Line 120: | ||
== More about unit testing in general == | == More about unit testing in general == | ||
The best book I know about unit testing is '''Pragmatic Unit Testing in Java with JUnit'' by Andrew Hunt and David Thomas. I know, this book is not called Pragmatic Unit Testing in PHP with SimpleTest. However, it is an excellent book - short, to the point, and very practical. Most of what it says is not specific to Java and JUnit and it is obvious how to apply it in our testing setup. | The best book I know about unit testing is '''Pragmatic Unit Testing in Java with JUnit'' by Andrew Hunt (no relation) and David Thomas. I know, this book is not called Pragmatic Unit Testing in PHP with SimpleTest. However, it is an excellent book - short, to the point, and very practical. Most of what it says is not specific to Java and JUnit and it is obvious how to apply it in our testing setup. | ||
[[Category:Developer]] | [[Category:Developer]] |
Revision as of 15:31, 30 June 2006
The purpose of unit testing is to test the individual parts of the program (functions, and methods of classes) to make sure that each individually does the right thing. Once unit testing has given you the confidence that each part works, then you should use other forms of testing to ensure that the different parts work together properly.
The unit testing framework is based on the SimpleTest framework. It was incorporated into Moodle by Nick Freear and Tim Hunt from The Open University.
Running the unit tests in Moodle
Running the basic tests
- Log in with an admin account.
- Go to the admin screen.
- Click on the Reports link near the bottom of the page.
- Click on the Run the unit tests link.
- Wait for the tests to run.
Options for running the tests
At the bottom of the tests page, there is form that lets you adjust the options used when running the tests.
Show passes as well as fails
Normally, only details of the tests that have failed are printed. Turning on this options shows details of all the passes too.
Show the search for test files
The tests to run are found automatically be searching the codebase for files whose names match test*.php in directories called simpletest. Turning on this option will print a list of the folders searched and the test files found. This is sometimes useful for debugging.
This option is particularly useful when one of your test files has a syntax error. When this happens, you sometimes just get a blank page with no error message. Turning on the show search option lets you see which test file it was that gave the error. If necessary, you can enable this option manually by adding "showsearch=1" to the end of the URL.
Run a thorough test (may be slow)
If you turn on this option, then as well as looking for files called test*.php, the search also looks for files called slowtest*.php.
To be useful, the full test run should find most bugs, but not take too long to complete. So if you have very, very detailed tests of an area of the code, it may be better to select a subset for everday testing, and only use the more detailed tests when a bug is reported, or you are doing new development in that area of the code.
This option is most useful when combined with the next option.
Only run tests in
Normally, tests from all parts of the codebase are run. However, when you are just doing development of one part of the code, that is a waste of time. You can type the name of a folder (for example mod/quiz) or a particular test file (for example lib/simpletest/testdatalib.php) and then only those tests will be run.
Instead of typing a path into this box, there is an easier way. Whenever a pass or fail is displayed, the name of the test file is printed. Each section of the path name is a link to run only the tests in that folder or file.
Writing new tests
As an example, suppose we wanted to start writing tests for the functions in the file 'question/editlib.php'.
Were to put the tests
If you have read the first half of this page and were paying attention, you can probably work out that you should create a folder called question/testeditlib, and create a file in there called something like testeditlib.php.
The skeleton of this file should look like:
<?php /** * Unit tests for (some of) question/editlib.php. * * @copyright © 2006 The Open University * @author T.J.Hunt@open.ac.uk * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package question */ /** */ require_once(dirname(__FILE__) . '/../../config.php'); global $CFG; require_once($CFG->libdir . '/simpletestlib.php'); // Include the test libraries require_once($CFG->dirroot . '/question/editlib.php'); // Include the code to test /** This class contains the test cases for the functions in editlib.php. */ class question_editlib_test extends UnitTestCase { function test_get_default_question_category() { // Do the test here/ } } ?>
That is, you have a class called something_test, and in that class you have lots of methods called test_something. Normally, you have one test method for each function you want to test, and you may as well called the test method test_name_of_function_being_tested.
Inside a test function
TODO
Test data
TODO
Further information
The simpletest documentation is at: http://simpletest.sourceforge.net/.
Changes to your existing code to make it work with unit testing
When code is being tested, it gets included from inside one of the simpletest library function. If the code is expecting to be run directly (for example, if it is a view.php or index.php function), you are likely to get errors becuase that expectation is no longer true.
Include paths
Includes like
require_once('../../config.php'); // Won't work.
won't work. Instead, the more robust option is
require_once(dirname(__FILE__) . '/../../config.php'); // Do this.
Access to global variables
Because your code was included from within a function, you can't access access global variables until you have done a global statement.
require_once(dirname(__FILE__) . '/../../config.php'); require_once($CFG->libdir . '/moodlelib.php'); // Won't work.
require_once(dirname(__FILE__) . '/../../config.php'); global $CFG; // You need this. require_once($CFG->libdir . '/moodlelib.php'); // Will work now.
More about unit testing in general
The best book I know about unit testing is 'Pragmatic Unit Testing in Java with JUnit by Andrew Hunt (no relation) and David Thomas. I know, this book is not called Pragmatic Unit Testing in PHP with SimpleTest. However, it is an excellent book - short, to the point, and very practical. Most of what it says is not specific to Java and JUnit and it is obvious how to apply it in our testing setup.