2013-08-26 13:39:00 +02:00
|
|
|
# Testing guide
|
|
|
|
|
|
|
|
|
|
|
|
## Testing controllers for compatibility with different monitoring datasources
|
2013-07-22 18:23:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
When it comes to writing controllers, it is important that your actions and queries work on every monitoring
|
|
|
|
datasource supported by icinga2 web. For this, the monitoring module provides a test library for controllers.
|
|
|
|
|
2013-08-26 13:39:00 +02:00
|
|
|
## The database setup for every testcase
|
2013-07-22 18:23:45 +02:00
|
|
|
|
|
|
|
When testing PostgreSQL and MySQL databases, the test library (normally) executes the following test procedure for every
|
|
|
|
test case:
|
|
|
|
|
|
|
|
- Log in to the rdbms as the user icinga_unittest with password icinga_unittest
|
|
|
|
- Use the icinga_unittest database (which must be existing)
|
|
|
|
- Drop all tables in the icinga_unittest database (so *NEVER* run unit tests on your production system)
|
|
|
|
- Create a new, clean database schema
|
|
|
|
|
|
|
|
If anything goes wrong during this procedure, the test will be skipped (because maybe you don't have a pgsql database, but
|
|
|
|
want to test mysql, for example)
|
|
|
|
|
2013-08-26 13:39:00 +02:00
|
|
|
## Setting up a test user and database in MySQL
|
2013-07-22 18:23:45 +02:00
|
|
|
|
|
|
|
In MySQL, it's best to create a user icinga_unittest@localhost, a database icinga_unittest and grant all privileges on
|
|
|
|
this database:
|
|
|
|
|
|
|
|
mysql -u root -p
|
|
|
|
mysql> CREATE USER `icinga_unittest`@`localhost` IDENTIFIED BY 'icinga_unittest';
|
|
|
|
mysql> CREATE DATABASE `icinga_unittest`;
|
|
|
|
mysql> GRANT ALL PRIVILEGES ON `icinga_unittest`.* TO `icinga_unittest`@`localhost`;
|
|
|
|
mysql> FLUSH PRIVILEGES;
|
|
|
|
mysql> quit
|
|
|
|
|
2013-08-26 13:39:00 +02:00
|
|
|
## Setting up a test user and database in PostgreSQL
|
2013-07-22 18:23:45 +02:00
|
|
|
|
|
|
|
In PostgreSQL, you have to modify the pg_hba database if you don't have password authentication set up (which often is
|
|
|
|
the case). In this setup the icinga_unittest user is set to trust authentication on localhost, which means that no
|
|
|
|
password is queried when connecting from the local machine:
|
|
|
|
|
|
|
|
sudo su postgres
|
|
|
|
psql
|
|
|
|
postgres=# CREATE USER icinga_unittest WITH PASSWORD 'icinga_unittest';
|
|
|
|
postgres=# CREATE DATABASE icinga_unittest;
|
|
|
|
postgres=# \q
|
|
|
|
bash$ createlang plpgsql icinga;
|
|
|
|
|
2013-08-26 13:39:00 +02:00
|
|
|
## Writing tests for icinga
|
|
|
|
|
2013-08-27 10:37:35 +02:00
|
|
|
Icinga has it's own base test which lets you easily require libraries, testing database and form functionality. The class resides in
|
|
|
|
library/Icinga/Test. If you write a test, just subclass BaseTestCase.
|
2013-08-26 13:39:00 +02:00
|
|
|
|
|
|
|
### Default test header
|
|
|
|
|
2013-08-27 10:37:35 +02:00
|
|
|
Before writing a test you should include the base test first
|
2013-08-26 13:39:00 +02:00
|
|
|
|
|
|
|
// @codingStandardsIgnoreStart
|
|
|
|
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php');
|
|
|
|
// @codingStandardsIgnoreEnd
|
|
|
|
|
|
|
|
Now you can simply include dependencies with predefined properties:
|
|
|
|
|
|
|
|
require_once BaseTestCase::$libDir . '/Web/Form.php';
|
|
|
|
require_once BaseTestCase::$appDir . '/forms/Config/AuthenticationForm.php';
|
|
|
|
|
|
|
|
BaseTestCase provides static variables for every directory in the project.
|
|
|
|
|
|
|
|
### Writing database tests
|
|
|
|
|
|
|
|
The base test uses the PHPUnit dataProvider annotation system to create Zend Database Adapters. Typically a
|
2013-08-27 10:37:35 +02:00
|
|
|
database test looks like this:
|
2013-08-26 13:39:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider mysqlDb
|
|
|
|
* @param Zend_Db_Adapter_PDO_Abstract $mysqlDb
|
|
|
|
*/
|
|
|
|
public function testSomethingWithMySql($mysqlDb)
|
|
|
|
{
|
|
|
|
$this->setupDbProvider($mysqlDb); // Drops everything from existing database
|
|
|
|
|
|
|
|
// Load a dump file into database
|
2013-08-27 10:37:35 +02:00
|
|
|
$this->loadSql($mysqlDb, BaseTestCase::$etcDir . '/etc/schema/mydump.mysql.sql');
|
2013-08-26 13:39:00 +02:00
|
|
|
|
|
|
|
// Test your code
|
|
|
|
}
|
|
|
|
|
|
|
|
Available data providers are: mysqlDb, pgsqlDb, oracleDb. The test will be skipped if a provider
|
|
|
|
could not be initialized.
|
|
|
|
|
|
|
|
### Write form tests
|
|
|
|
|
|
|
|
BaseTestCase holds method to require form libraries and create form classes based on class names.
|
|
|
|
|
|
|
|
public function testShowModifiedOrder()
|
|
|
|
{
|
|
|
|
$this->requireFormLibraries();
|
|
|
|
$form = $this->createForm(
|
|
|
|
'Icinga\Form\Config\AuthenticationForm',
|
|
|
|
array(
|
|
|
|
'priority' => 'test-ldap,test-db'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
// Testing your code
|
|
|
|
}
|
|
|
|
|
2013-08-27 10:37:35 +02:00
|
|
|
The second parameter of createForm() can be omitted. You can set initial post request data as
|
|
|
|
an array if needed.
|
2013-07-22 18:23:45 +02:00
|
|
|
|
2013-08-26 13:39:00 +02:00
|
|
|
## Writing tests for controllers
|
2013-07-22 18:23:45 +02:00
|
|
|
|
|
|
|
When writing tests for controllers, you can subclass the MonitoringControllerTest class underneath monitoring/test/php/testlib:
|
|
|
|
|
|
|
|
class MyTestclass extends MonitoringControllerTest
|
|
|
|
{
|
|
|
|
// test stuff
|
|
|
|
}
|
|
|
|
|
|
|
|
This class handles a lot of depenendency resolving and controller mocking. In order to test your action correctly and
|
|
|
|
without side effects, the TestFixture class allows your to define and set up your faked monitoring results in the backend
|
|
|
|
you want to test:
|
|
|
|
|
|
|
|
use Test\Monitoring\Testlib\Datasource\TestFixture;
|
|
|
|
|
|
|
|
class MyTestclass extends MonitoringControllerTest
|
|
|
|
{
|
|
|
|
public function testSomething()
|
|
|
|
{
|
|
|
|
$fixture = new TestFixture();
|
|
|
|
// adding a new critical, but acknowledged host
|
|
|
|
$fixture->addHost("hostname", 1, ObjectFlags::ACKNOWLEDGED())
|
|
|
|
|
|
|
|
// add a comment to the host (this has to be done before adding services)
|
|
|
|
->addComment("author", "comment text")
|
|
|
|
|
|
|
|
// assign to hostgroup
|
|
|
|
->addToHostgroup("myHosts")
|
|
|
|
|
|
|
|
// and add three services to this host
|
|
|
|
->addService("svc1", 0) // Service is ok
|
|
|
|
->addService("svc2", 1, ObjectFlags::PASSIVE) // service is warning and passive
|
|
|
|
->addService("svc3", 2, null, array("notes_url" => "test.html")) // critical with notes url
|
|
|
|
->addComment("author", "what a nice service comment") // add a comment to the service
|
|
|
|
->addToServicegroup("alwaysdown"); // add svc3 to servicegroup
|
|
|
|
|
|
|
|
// Create the datasource from this fixture, here in MySQL
|
|
|
|
$this->setupFixture($fixture, "mysql");
|
|
|
|
|
|
|
|
// ... do the actual testing (discussed now)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
After the call to setupFixture() your backend should be ready to be tested. Setting up the controller manually would
|
|
|
|
force you to go through the whole bootstrap. To avoid this the MonitoringControllerTest class provides a 'requireController'
|
|
|
|
method which returns the Controller for you with an already set up backend using your previously defined testdata:
|
|
|
|
|
|
|
|
$controller = $this->requireController('MyController', 'mysql');
|
|
|
|
// controller is now the Zend controller instance, perform an action
|
|
|
|
$controller->myAction();
|
|
|
|
$result = $controller->view->hosts->fetchAll();
|
|
|
|
|
|
|
|
This example assumes that the controller populates the 'host' variable in the view, so now you can assert the state of
|
|
|
|
the result according to your test plan.
|