📝 tests README : retrofit of the support/3.2 version

This commit is contained in:
Pierre Goiffon
2024-02-14 15:16:58 +01:00
parent aa53de467d
commit c020de59a7

View File

@@ -1,15 +1,29 @@
# PHP unitary tests
## Where should I add my test?
Documentation on creating and maintaining tests in iTop.
- Covers an iTop PHP class or method?
- Most likely in "unitary-tests".
- Covers the consistency of some data through the app?
- Most likely in "integration-tests".
## Tests prerequisites
Install iTop with default setup options :
## Prerequisites
### PHPUnit configuration file
A default file is located in `/tests/php-unit-tests/phpunit.xml.dist`
If you need to customize it, copy it to `phpunit.xml` (not versioned).
### PHP configuration
* PHPUnit configuration file
- `memory_limit`: as the tests are for the most part ran in the same process, memory usage may become an issue! A default value is set in default PHPUnit configuration XML file, don't hesitate to update it if needed
* PHP CLI php.ini
- enable OpCache
- disable Xdebug (xdebug.mode=off) : huge performance improvements (between X2 and X3), and we can still debug using PHPStorm !
### Dependencies
Whereas iTop dependencies are bundled inside its repository, the tests dependencies are not, and must be added manually. To do so, run `composer install` in the `/tests/php-unit-tests` directory.
### iTop instance prerequisites to run its test suite
Install iTop with default setup options :
- Configuration Management options : everything checked
- Service Management for Enterprises
- Simple Ticket Management + Customer portal
@@ -18,14 +32,119 @@ Install iTop with default setup options :
Plus :
- Additional ITIL tickets : check Known Errors Management and FAQ
## Create an iTop PHPUnit test
## What about skipped tests ?
### Where should I add my test?
- Covers an iTop PHP class or method? => Most likely in the `unitary-tests` directory
- Covers the consistency of some data through the app? => Most likely in `integration-tests` directory
### iTop test parent classes
iTop provides PHPUnit TestCase children that provides some helpers and setUp/tearDown overrides :
- `\Combodo\iTop\Test\UnitTest\ItopTestCase` : for the most simple iTop tests
- `\Combodo\iTop\Test\UnitTest\ItopDataTestCase` : to get a started metamodel and have cleanup of CRUD operations on iTop objects (transactions by default)
- `\Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase` : to test a non standard datamodel (available since iTop 2.7.9, 3.0.4, 3.1.0 N°6097)
### Naming convention
* to test `MyClass` class then create a `MyClassTest` class
* to test `MyMethod` method, the corresponding test method should be named `testMyMethod`
Source [PHPUnit Manual Chapter 2. Writing Tests for PHPUnit](https://docs.phpunit.de/en/9.6/writing-tests-for-phpunit.html#writing-tests-for-phpunit)
### What about skipped tests ?
A test can be marked as skipped by using the `markTestAsSkipped()` PHPUnit method. Please use it only for temporary disabled tests, for example the ones that are pushed before their corresponding fix.
For other cases like non-relevant data provider cases, just mark the test valid with `assertTrue(true)` and `return`.
For other cases like non-relevant data provider cases, just mark the test valid with `assertTrue(true)` and `return`.
## How do I make sure that my tests are efficient? (performences)
## Tips: generic PHPUnit
### Disable a test
```php
$this->markTestSkipped('explanation');
```
### Test an exception
Just before calling the code throwing the exception, call `\PHPUnit\Framework\TestCase::expectException`. You might also use `expectExceptionMessage` and/or `expectExceptionMessageMatches`.
Example :
```php
// Try to delete the tag, must complain !
$this->expectException(DeleteException::class);
$this->expectExceptionMatches('/'.$this->GetKey().'/');
$oTagData->DBDelete();
```
Warning : when the condition is met the test is finished and following code will be ignored !
Another way to do is using try/catch blocks, for example :
```php
$validator = new FormValidator();
try {
$validator->validate(
new DateTimeImmutable('2020-01-01'),
new DateTimeImmutable('1999-01-01'),
-3,
''
);
$this->fail('FormValidationException was not thrown');
} catch (AssertionFailedError $e) {
throw $e; // handles the fail() call just above
} catch (FormValidationException $e) {
$this->assertSame(
[
'End must be after start',
'The new id must be greater than 0',
'Description can not be empty',
],
$e->getErrors()
);
}
```
## Tips: iTop tests
### Load an iTop class which is outside the autoloader
When running a test extending ItopDataTestCase you'll get all of the iTop classes loaded (Composer autoloader + iTop autoloader including installed modules)
For ItopTestCase files, you may need to load specific iTop classes that aren't part of the Composer autoloader. If so, since N°5608 (introduced in iTop 2.7.9, 3.0.3, 3.1.0-1) you can use :
- ItopTestCase::RequireOnceItopFile
- ItopTestCase::RequireOnceUnitTestFile
### Add a User context
Use `UserRights::Login()`
## Test performances
### Memory limit
As the tests are run in the same process, memory usage
may become an issue as soon as tests are all executed at once.
Fix that in the XML configuration in the PHP section
```xml
<ini name="memory_limit" value="512M"/>
```
### Measure the time spent in a test
Simply cut'n paste the following line at several places within the test function:
```php
if (isset($fStarted)) {echo 'L'.__LINE__.': '.round(microtime(true) - $fStarted, 3)."\n";} $fStarted = microtime(true);
```
### Derive from the relevant test class
@@ -65,26 +184,10 @@ See also `@beforeClass` and `@afterClass` to handle cleanup.
If you can't, then ok you will have to isolate it!
## Tips
### Memory limit
As the tests are run in the same process, memory usage
may become an issue as soon as tests are all executed at once.
Fix that in the XML configuration in the PHP section
```xml
<ini name="memory_limit" value="512M"/>
```
### Measure the time spent in a test
Simply cut'n paste the following line at several places within the test function:
```php
if (isset($fStarted)) {echo 'L'.__LINE__.': '.round(microtime(true) - $fStarted, 3)."\n";} $fStarted = microtime(true);
```
## PHPUnit process isolation
### Understand tests interactions
@@ -133,14 +236,14 @@ the exact same effect as `@runTestsInSeparateProcesses`.
Note : this option is documented only in the [attributes part of the documentation](https://docs.phpunit.de/en/10.0/attributes.html).
### Traps
#### When it is a matter of stars
#### Doc block comment format : when it is a matter of stars
```php
/*
* @runTestsInSeparateProcesses
```
This won't work because the comment MUST start with `/**` (two stars) to be considerer by PHPUnit.
#### SetupBeforeClass called more often than expected
#### SetupBeforeClass called more often than expected when running in separate processes
`setupBeforeClass` is called once for the class **in a given process**.