I have more than 1000s of unit tests for my application and it takes hour to run the test and get the results. how do we configure to run phpunit to run all only those testcases that has dependency / impact of the current change.
E.g if I change a method in the class A and this method is called in one of the method of Class B. I have Unit tests written for class A, B & C. I want to execute only testcases for class A's method that has been changed and class's B method that has called it.
Edit: I'm using Jenkins to automatically test the code ,how will my phpunit know what has been changed so it will trigger the phpunit for impacted code change.
Related
I'm trying to set up a testing suite for my Symfony 3 app, and I'm wondering what the correct method for setting up the test database is. I've found this article, but it doesn't actually explain how to add fixtures programmatically.
Also, it appears their example sets up the test database for every test.
Is there a way to setup a test database which is automatically loaded with fixtures when phpunit is run? The official documentation is kind of sparse
Symfony has different environments you can operate in. By default those are prod(production), dev(developement) and test. Although it may not be exactly what you want, you can configure different config, paramaters, routes and so on for each environment. Read the official documentation for more info but yeah, you can setup your parameters.yml file for test mode which could have a different database configured there.
https://symfony.com/doc/current/configuration/environments.html
If you extend your TestCases from KernelTestCase or WebTestCase, basically extend from \PHPUnit_Framework_TestCase you have methods like setUpBeforeClass() or setUp() which are run by PhpUnit before your test/test cases is/are executed.
Use this to e.g. create your fixtures, load your SQL file or whatever and however you might require your prerequisites for your tests.
In PHPUnit, you can annotate a test-case class (#runTestsInSeparateProcesses) or a test function (#runInSeparateProcess) to run tests in process isolation. There is also a setting in the phpunit.xml config file (processIsolation = "true") to run all tests in separate processes.
I have a group of test-case classes which all inherit from a database-related abstract test class that I need to run in process isolation. But annotations aren't inherited from parent classes. Is there a way for me to mark these test-case classes to run in separate processes by #group, or directory, or some other specifier, without having to mark each test-case class with #runTestsInSeparateProcesses?
No, this is currently not possible. Feel free to open a feature request.
Today I bumped into something strange regarding an Artisan Command's lifecycle.
I added an artisan command named cronjobs:MyCommand.
Created the necessary files and classes.
Class MyCommand extends BaseCommand.
BaseCommand is something I put up to benchmark command line operations.
It consists of a constructor and destructor. The constructor keeps track of
the starting time of the operation, the destructor logs the current time minus
the starting time in a log table.
To my surprise I found out that the __destruct() function on my BaseCommand is
called 5 times in total every time I issue the cronjobs:MyCommand via artisan.
Is this normal behavior and if so how am I supposed to take care of logging instead?
Further testing with Symfony 2's command class showed that this is a problem native to Symfony 2, not so much with laravel 4.
Using a constructor/destructor in an artisan command's class (or its parent) in any useful way seems impossible at this point in time.
Any input is still highly appreciated!
Issue seems still not fixed.. I had also creaed a basecommand with __destruct method which is gettigng executed multiple times.
I created a shutdown method in my basecommand and calling at the end of mycommand.
This question: Run PHPUnit Tests in Certain Order has an accepted answer which I agree with, but the design problem is with PHP and PHPUnit.
The project I'm testing uses ZF2 and Doctrine. The AbstractHttpControllerTestCase has a method "dispatch" which instantiates a ZF2 Application and goes through all the steps of creating the Response object. These tests are annotated with #covers to ensure other methods aren't covered by running requests during a test. The requests may involve view scripts which invoke view helpers which use all sorts of services, so it becomes infeasible to mock all services used during a given request (and this code would become tedious to copy and maintain for each test).
PHPUnit has the ability to run tests in a separate process, it does this by forking a new PHP instance and feeding it compiled code templates (weird stuff). It will then include all files listed by get_included_files(), which includes everything that ever hit the autoloader. Even with preserveGlobalState disabled, it will still include everything that's been touched by all prior tests in the new process.
Some of the dependencies (installed through composer) use static methods, classes marked final or both. Static methods can be mocked by PHPUnit, final classes have to be overloaded using Mockery as PHPUnit will flat out refuse to create mock objects of final classes. Overloading classes and functions (using the namespace trick) must be done in separate processes as to not influence subsequent tests. So far, so good.
Enter a test which overloads a dependency to set expectations on static methods (on a class which may or may not be marked final), or to set expectations on objects which are not yet instantiated. This will only work if none of the prior tests have ever touched the class to overload and set expectations on, or it'll fail with a "cannot redeclare class" error. PHPUnit has tried to be helpful and included everything to recreate the test environment in the subprocess, but as a result ruins the test case.
Therefore, it would be incredibly useful to mark tests with e.g. "#group isolated" and have those tests run before any other tests without having to invoke PHPUnit twice (besides the inconvenience of it, it would ruin coverage analysis).
Alternatively, if there's a way to override a class that already exists in PHP 5.5, that would allow the stricken test case to fix its precondition. But that's probably not going to happen (runkit is not an acceptable answer in any case).
My Yii app getting phpunit coverage in controllers, models, components, modules but not any views. The problem is that code coverage loader in phpunit includes the view file during preparing a coverage report. Views with forms have calls $this->beginWidget which causes a crash since there is no $this context.
Views dont really have important code or logic but still they have some conditions and even loops to call renderPartial so it would be good to get a view code also covered.
Is there a solution to this problem?
Have you tried extending CWebTestCase? Generally when writing unit tests, you have fixtures and things to provide the necessary data - but with tests on views and 'functional' tests, for web-apps, it's generally easiest to mimic a browser and have it perform actions on the web app as if a user was actually using it. Currently, this mimicking is most easily done with Selenium (in my opinion).
The Yii Guide on Functional Testing is a good place to start as well as the Selenium Documentation. There's also this book that goes over using selenium (I'm not sure if the newest edition does, but I know the previous release with Publication Date: August 11, 2010 did), and Larry Ullman's Yii Book will have chapters on testing and the usage of Selenium in functional tests when he's completed that chapter.
Hope this helps!
Update to further explain CWebTestCase
CWebTestCase extends PHPUnit_Extensions_SeleniumTestCase which directly implements a functional testing foundation that you can use within phpunit in order to test views, test widget creation inside of views, assert that text exists, 'click' on links, etc. These tests are still run from the command line though they require that Selenium-RC server be started upon the test being run and they require a valid browser being configured. A valid browser can be configured with as little code as the following placed inside of the setUp() function:
$this->setBrowser('*firefox /usr/lib/firefox/firefox-bin');
Stating that code coverage cannot be provided by CWebTestCase is not true, as CWebTestCase extends PHPUnit_Extensions_SeleniumTestCase, which provides the following as quoted from the documentation:
PHPUnit_Extensions_SeleniumTestCase can collect code coverage
information for tests run through Selenium:
Copy PHPUnit/Extensions/SeleniumTestCase/phpunit_coverage.php into
your webserver's document root directory. In your webserver's php.ini
configuration file, configure
PHPUnit/Extensions/SeleniumTestCase/prepend.php and
PHPUnit/Extensions/SeleniumTestCase/append.php
as the auto_prepend_file and auto_append_file, respectively. In your test
case class that extends PHPUnit_Extensions_SeleniumTestCase, use
protected $coverageScriptUrl = 'http://host/phpunit_coverage.php';
to configure the URL for the phpunit_coverage.php script.