pgee70 / ci-phpunit-test
An easier way to use PHPUnit with CodeIgniter 3.x
Requires
- php: >=7.3
- nikic/php-parser: ^4.2
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-24 01:07:18 UTC
README
This is a fork of kenjis/ci-phpunit-test 3.x, published on
Packagist as pgee70/ci-phpunit-test. Upstream's last release targets the original
bcit-ci/CodeIgniter 3.1.13, PHP 7.3 - 8.2 and PHP-Parser 4. It doesn't
work with the maintained CodeIgniter 3 fork,
pocketarc/codeigniter (3.4.x), with PHP 8.4, or with PHP-Parser 5.
This fork keeps upstream's API and documentation, and changes only what those three need.
What is different from upstream
pocketarc/codeigniter's bootstrap
pocketarc/codeigniter passes the core classes their dependencies through their constructors. For example,
CI_Hooks and CI_URI take the CI_Config object, CI_Utf8 the charset, CI_Security the charset and
CI_Input the CI_Security object. They no longer reach for globals.
ci-phpunit-test boots CodeIgniter with its own copy of system/core/CodeIgniter.php
(_ci_phpunit_test/replacing/core/CodeIgniter.php), and rebuilds the core objects in reset_instance()
(_ci_phpunit_test/functions.php). Both now:
- load
Configfirst; - pass each class the constructor argument pocketarc expects;
- set
CI_VERSIONto3.4.2.
With upstream's files, those classes are built without their arguments, and the bootstrap stops with an
ArgumentCountError.
PHP 8.4
- PHP 8.4 deprecates implicitly nullable parameters (
array $x = null). Every such parameter now has an explicit?type, for example inCIPHPUnitTest::init(),CIPHPUnitTestAutoloader::__construct()andMonkeyPatch::verifyInvoked*(). Without that, every test run prints deprecation notices. composer.jsonrequiresphp >= 8.4,ext-posixandext-sodium.
PHP-Parser 5 for Monkey Patching
Monkey Patching parses each included source file with nikic/php-parser
and rewrites it: exit(), patched functions, patched methods and patched constants. PHP-Parser 5 dropped the
API upstream used (ParserFactory::create() with PREFER_PHP5/PREFER_PHP7, and the Lexer options), so:
- The patchers create their parser with
ParserFactory::createForHostVersion(), so source files are parsed with the grammar of the PHP version running the tests. The method-patch proxy usescreateForNewestSupportedVersion(). - PHP-Parser 5's lexer takes no options and always records token positions, so the
LexerwithusedAttributes => [startTokenPos, endTokenPos]is gone. - As upstream does, a patched file is regenerated with
PrettyPrinter\Standard. Its line numbers therefore differ from the source file, which affects stack traces, Xdebug breakpoints and code coverage of patched files. Turn Monkey Patching off for coverage runs. - The
php_parsersetting ofMonkeyPatchManager::init()is ignored now. The sampleBootstrap.phpanddocs/HowToWriteTests.mdstill show it, and leaving it in does no harm. - Only the PHP-Parser 4.6+ patcher (
patcher/4.x) is kept, and it works with PHP-Parser 5. The patchers for PHP-Parser 2.x, 3.x and 4.0 - 4.5 have been removed. So have the copies of PHP-Parser 2.1.1 and 3.1.5 bundled for installs without Composer. PHP-Parser now has to come from Composer (nikic/php-parser ^5.1, a requirement of this package).
Smaller changes
CI_Loader::model()in tests: if the CodeIgniter instance already has a property with the model's name, for example because the model is already loaded, it logs a debug message and returns the loader. Upstream threwRuntimeException.CIPHPUnitTestLoggeraddsgetLogs()anddidLogsContain($level, $message), which matches part of a message. Upstream'sdidLog()needs the whole message.reset_instance()stores theUtf8object in theUNIglobal andURIin theURIglobal, as CodeIgniter does.
Not updated
.github/workflows/phpunit.ymlis upstream's. It runs against kenjis/ci-app-for-ci-phpunit-test on PHP 7.3 - 8.2 and doesn't test this fork.docs/and_ci_phpunit_test/ChangeLog.mdare upstream's. The API they describe still holds; their version and install notes don't.
Warning
Upstream recommends upgrading to CodeIgniter4.
An easier way to use PHPUnit with CodeIgniter 3.x.
- You don't have to modify CodeIgniter core files at all.
- You can write controller tests easily.
- Nothing is untestable, maybe.
- Well documented.
Requirements
- PHP 8.4 or later, with the
posixandsodiumextensions - pocketarc/codeigniter 3.4.x
- For the original bcit-ci CodeIgniter 3.1.x on older PHP, use upstream kenjis/ci-phpunit-test.
- nikic/php-parser 5.1 or later, installed by Composer as a dependency
- PHPUnit 10.5. Upstream supports 9.3 or later; this fork is used with 10.5.
Optional
- NetBeans
- Go to Project Properties > Testing > PHPUnit, check Use Custom Test Suite checkbox, and select
application/tests/_ci_phpunit_test/TestSuiteProvider.php.
- Go to Project Properties > Testing > PHPUnit, check Use Custom Test Suite checkbox, and select
Change Log
Upstream's Change Log goes up to its last release. For the
fork's changes, see What is different from upstream and git log.
Folder Structure
codeigniter/
├── application/
│ └── tests/
│ ├── _ci_phpunit_test/ ... don't touch! files ci-phpunit-test uses
│ ├── Bootstrap.php ... bootstrap file for PHPUnit
│ ├── DbTestCase.php ... DbTestCase class
│ ├── TestCase.php ... TestCase class
│ ├── controllers/ ... put your controller tests
│ ├── libraries/ ... put your library tests
│ ├── mocks/
│ │ └── libraries/ ... mock libraries
│ ├── models/ ... put your model tests
│ └── phpunit.xml ... config file for PHPUnit
└── vendor/
Installation
Install with Composer: Monkey Patching needs PHP-Parser 5 from Composer.
Composer Installation
$ cd /path/to/codeigniter/ $ composer require pgee70/ci-phpunit-test:dev-main --dev
And run install.php:
$ php vendor/pgee70/ci-phpunit-test/install.php --from-composer
- The above command always overwrites existing files.
- You must run it at CodeIgniter project root folder.
- You can specify your
applicationandpublicfolder with option arguments, if you use custom folder paths.
$ php vendor/pgee70/ci-phpunit-test/install.php -a <application_dir> -p <public_dir> -t <unittest_dir>
So the default would be:
$ php vendor/pgee70/ci-phpunit-test/install.php -a application -p public -t application/tests
- But some paths may be not correct, in that case, please fix them in tests/Bootstrap.php.
Upgrading
$ cd /path/to/codeigniter/ $ composer update pgee70/ci-phpunit-test
Read What is different from upstream.
Coming from kenjis/ci-phpunit-test
composer remove kenjis/ci-phpunit-test, thencomposer require pgee70/ci-phpunit-test:dev-main --dev.- In
application/tests/Bootstrap.php, change thevendor/kenjis/ci-phpunit-testpath inCI_PHPUNIT_TESTPATHtovendor/pgee70/ci-phpunit-test(see below). - Remove the
php_parsersetting fromMonkeyPatchManager::init(). It is ignored, so this step is optional.
If you want to remove application/test/_ci_phpunit_test/
If you're upgrading from a previous version of ci-phpunit-test that created
an application/test/_ci_phpunit_test directory and now want to directly use
ci-phpunit-test from Composer, you have a couple of additional steps:
- Delete the old test library directory:
$ rm -rf /path/to/codeigniter/application/tests/_ci_phpunit_test - Edit the
application/tests/Bootstrap.phpfile. At the bottom of the "set the main path constants" section, add the following:define('CI_PHPUNIT_TESTPATH', implode( DIRECTORY_SEPARATOR, [dirname(APPPATH), 'vendor', 'pgee70', 'ci-phpunit-test', 'application', 'tests', '_ci_phpunit_test'] ).DIRECTORY_SEPARATOR);
And replace any references to__DIR__ . '/_ci_phpunit_test/orTESTPATH . '_ci_phpunit_testwithCI_PHPUNIT_TESTPATH . '. (So, for example,__DIR__ . '/_ci_phpunit_test/CIPHPUnitTest.php'would becomeCI_PHPUNIT_TESTPATH . '/CIPHPUnitTest.php'.)
How to Run Tests
You need to install PHPUnit before running tests.
If you use Composer:
$ composer require phpunit/phpunit --dev
Run All Tests
$ cd /path/to/codeigniter/ $ vendor/bin/phpunit -c application/tests/ PHPUnit 9.5.4 by Sebastian Bergmann and contributors. ... 3 / 3 (100%) Time: 00:00.102, Memory: 12.00 MB OK (3 tests, 3 assertions) Generating code coverage report in Clover XML format ... done [00:00.002] Generating code coverage report in HTML format ... done [00:00.012]
To generate coverage report, Xdebug is needed.
Run a Single Test
If you want to run a single test case file:
$ vendor/bin/phpunit -c application/tests/ application/tests/models/Category_model_test.php
How to Write Tests
As an example, a test case class for Inventory_model would be as follows:
<?php class Inventory_model_test extends TestCase { public function setUp(): void { $this->resetInstance(); $this->CI->load->model('Inventory_model'); $this->obj = $this->CI->Inventory_model; } public function test_get_category_list() { $expected = [ 1 => 'Book', 2 => 'CD', 3 => 'DVD', ]; $list = $this->obj->get_category_list(); foreach ($list as $category) { $this->assertEquals($expected[$category->id], $category->name); } } public function test_get_category_name() { $actual = $this->obj->get_category_name(1); $expected = 'Book'; $this->assertEquals($expected, $actual); } }
As an example, a test case class for Welcome controller would be as follows:
<?php class Welcome_test extends TestCase { public function test_index() { $output = $this->request('GET', 'welcome/index'); $this->assertStringContainsString( '<title>Welcome to CodeIgniter</title>', $output ); } }
See How to Write Tests for details.
Function/Class Reference
See Function and Class Reference.
Tips
See Tips.
Stand-alone Packages
Some features of ci-phpunit-test are available in the following standalone packages.
