How to test statements which depends on specific PHP version with PHPUnit? - php

I have a construct like this:
class Foo
{
public function doFoo($value = '')
{
if (function_exists('foo'))
{
return foo($value);
}
// if php version does not support foo()
// ...
}
}
How can i test this code with PHPUnit to achieve a 100% code coverage if the existence of the function foo depends on the installed PHP version (for this example i assume that the function exists, otherwise a code coverage of 100% is impossible). Is there a way to disable/enable PHP functions at runtime?
Any ideas how to solve it?
EDIT:
i have found a solution: the Advanced PHP debugger / PECL extension provide a function *rename_function* for this purposes.
bool rename_function ( string $original_name , string $new_name )
Renames a orig_name to new_name in the global function table. Useful for temporarily
overriding built-in functions.

You can define a simulation of foo() in your test method. Do something like this:
<?php
/**
* Your test method
*/
public function testSomething () {
// if the function not exists, create a simulation
if(!function_exists('foo')) {
function foo() {
return $aValue;
}
}
// your test code ...
}
This works because a function may defined into another method or function. Although they are defined in the method they are globally available.
Using the pecl extension is not required. Further it potentially pollutes the test execution environment and at least adds unneeded requirements.
Furthermore note that PHPUnit as from version 3.6 supports the annotations #codeCoverageIgnore, #codeCoverageIgnoreStart, #codeCoverageIgnoreEnd to can be used to exclude classes, methods or parts of code from coverage analysis.

Well, in PHP 5.3 and higher You can override the behavior of any PHP function.
Look at this
namespace Test
{
function function_exists($function)
{
return false;
}
var_dump(function_exists('var_dump')); // bool(false)
}
This is possible due to the PHP's fallback mechanism. In short, when it encounters a function it first checks if the function exists in the current namespace. If not, it falls back to the global namespace.

Related

Phpunit does not execute effective parent test case?

I'm currently testing a wrapper to an API with PHPUnit (CLI).
Due to the nature of the tests, I can pretty much use the same code for testing two different use cases. The only difference is in the values I send to the API as parameters.
So, I decided to write a class DefaultTest, where I test the API using default values used by the API and a second CustomTest(Case) where I test my parameter container with differing values. CustomTest inherites from DefaultTest, as all the functions used for validating the returned data are equivalent in both cases.
Here's some code for your understanding:
class DefaultTest extends PHPUnit_Framework_TestCase {
public function testAPIMethod()
{
$this->checkParameterContainer();
$this->validateResults();
}
public function checkParameterContainer()
{
/* Set up default parameter container */
}
public function validateResults()
{
/* Validate the results */
}
}
class CustomTest extends DefaultTest {
public function checkParameterContainer()
{
/* Set up custom parameter container */
}
public function validateResults()
{
parent::validateResult();
}
}
PHPUnit takes the child class, executes the testAPIMethod, leading to CustomTest::checkParameterContainer() and DefaultTest::validateResults() being executed.
But DefaultTest's testAPIMethod is never executed, as DefaultTest::checkParameterContainer() is never called.
Both classes are fully valid TestCases and DefaultTest is executed normally when not specialized.
So, my question for you guys: Why is that? Do I miss something here? Is this by design?
In case, somebody needs it: PHPUnit uses reflection to find test methods on each class, but will not search in parent classes. So the following will be needed in the child test class:
public function testAPIMethod()
{
parent::testAPIMethod();
}

Need advice on doing PHP unit test on complex methods within a class

I am a beginner of unit testing and having difficulty of testing an algorithm (which is executable by cron in actual implementation) that is within a PHP class with functions that don't have arguments as well as depending on other classes for data sources, e.g. this one:
class Mailing_System_Algo {
function __construct()
{
//Run the mailing system method
$this->execute_mailing_system();
}
function execute_mailing_system()
{
$Class_Data_Source = new Data_Source;
$groups = $Class_Data_Source->get_groups();
//Proceed only if groups are defined
if (!(empty($groups))) {
//rest of the algo codes here-very long and lots of loops and if statements
}
}
}
I would like treat the algo function like a blackbox so I won't be altering anything on their codes when I do the test. But how can I start testing them by feeding them inputs if the execute_mailing_system will run right away the moment the class is instantiated?
Supposing I would like to check if the algo will execute with or without groups, how can I provide an input in my unit test codes for $groups?
This is how my test case would look like:
class WP_Test_Mailing_System_Algo extends WP_UnitTestCase {
/**
* Run a simple test to ensure that the tests are running
*/
function test_tests() {
//no problem here
$this->assertTrue( true );
}
function test_if_algo_wont_run_if_no_groups_provided {
//Instantiate, but won't this algo run the construct function rightaway?
$Mailing_System_Algo = new Mailing_System_Algo;
//rest of the test codes here
//how can I access or do detailed testing of execute_mailing_system() function and test if it won't run if groups are null or empty.
//The function does not have any arguments
}
}
Of course there are lots of tests that I would be writing but I'm currently stuck on this one. This is the first test that I would need to execute. But I have a problem on how to get started doing this. I believe that once I get the technique right, the rest of the tests would be straightforward. I would appreciate any of your inputs and help..Thanks.
There is two flaws with the code that will hamper testing:
Constructor does Real Work
Hard-Coded Dependencies
You can improve this by changing the class to
class Mailing_System_Algo
{
public function __construct()
{
// constructors should not do work
}
public function execute_mailing_system(Data_Source $Class_Data_Source)
{
$groups = $Class_Data_Source->get_groups();
//Proceed only if groups are defined
if (!(empty($groups))) {
//rest of the algo codes here-very long and lots of loops and if statements
}
}
}
This is way, you can replace your Data_Source with a Mock or Stub, returning defined test values.
If this is not an option, have a look at the Test Helper extension:
https://github.com/sebastianbergmann/php-test-helpers¹
In particular, have a look at set_new_overload(), which can be used to register a callback that is automatically invoked when the new operator is executed.
¹ the Test-Helper extension is superseded by https://github.com/krakjoe/uopz

Unit testing of functions

I have got a PHP file in which there are some functions (not included in a class). I am using PHPUnit to testing. When I try to generate in a simply way a test file from a file containing functions, the log says:
Could not find class...
Is there any possibility to test functions which are not methods?
Yes, you can with something like this:
includes/functions.php
function my_function() {
return true;
}
tests/MyFunctionTest.php
require_once '../includes/functions.php';
class MyFunctionTest extends PHPUnit_Framework_TestCase
{
public function testReturnValue()
{
$return_value = my_function();
$this->assertTrue($return_value);
}
}
So as long as your function is within scope you can call it from your test method just like any other PHP function in any other PHP framework or project.
If I'm right then PhpUnit works only with classes hence methods. So just convert them into the methods for testing purpose. Shouldn't be hard.

Is it possible to overwrite a function in PHP

Can you declare a function like this...
function ihatefooexamples(){
return "boo-foo!";
};
And then redeclare it somewhat like this...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
Is it possible to overwrite a function that way?
Any way?
Edit
To address comments that this answer doesn't directly address the
original question. If you got here from a Google Search, start here
There is a function available called override_function that actually fits the bill. However, given that this function is part of The Advanced PHP Debugger extension, it's hard to make an argument that override_function() is intended for production use. Therefore, I would say "No", it is not possible to overwrite a function with the intent that the original questioner had in mind.
Original Answer
This is where you should take advantage of OOP, specifically polymorphism.
interface Fooable
{
public function ihatefooexamples();
}
class Foo implements Fooable
{
public function ihatefooexamples()
{
return "boo-foo!";
}
}
class FooBar implements Fooable
{
public function ihatefooexamples()
{
return "really boo-foo";
}
}
$foo = new Foo();
if (10 == $_GET['foolevel']) {
$foo = new FooBar();
}
echo $foo->ihatefooexamples();
Monkey patch in namespace php >= 5.3
A less evasive method than modifying the interpreter is the monkey patch.
Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own.
Ninja skills
Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces.
Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. As this topic, fallback to global functions, aims to explain.
If you don't provide a namespace when calling a function, PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. For our example if you are calling print_r(); from namespace My\Awesome\Namespace; What PHP does is to first look for a function called My\Awesome\Namespace\print_r(); then My\Awesome\print_r(); then My\print_r(); until it finds the PHP built in function in the global namespace \print_r();.
You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists.
Expect a fatal error to the likes of:
Fatal error: Cannot redeclare print_r()
But nothing stops you, however, from doing just that within the scope of a namespace.
Patching the monkey
Say you have a script using several print_r(); calls.
Example:
<?php
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
But you later change your mind and you want the output wrapped in <pre></pre> tags instead. Ever happened to you?
Before you go and change every call to print_r(); consider monkey patching instead.
Example:
<?php
namespace MyNamespace {
function print_r($object)
{
echo "<pre>", \print_r($object, true), "</pre>";
}
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
}
Your script will now be using MyNamespace\print_r(); instead of the global \print_r();
Works great for mocking unit tests.
nJoy!
Have a look at override_function to override the functions.
override_function — Overrides built-in
functions
Example:
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
short answer is no, you can't overwrite a function once its in the PHP function scope.
your best of using anonymous functions like so
$ihatefooexamples = function()
{
return "boo-foo!";
}
//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
return "really boo-foo";
}
http://php.net/manual/en/functions.anonymous.php
You cannot redeclare any functions in PHP. You can, however, override them. Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want.
So, keep in mind that when you override a function, you lose it. You may want to consider keeping it, but in a different name. Just saying.
Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function.
Example:
rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
I would include all functions of one case in an include file, and the others in another include.
For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really }
It helps the readability / maintenance of your program, having all functions of the same kind in the same inc.
Then at the top of your main module
if ($_GET['foolevel'] == 10) {
include "really.inc";
}
else {
include "simple.inc";
}
You could use the PECL extension
runkit_function_redefine — Replace a function definition with a new implementation
but that is bad practise in my opinion. You are using functions, but check out the Decorator design pattern. Can borrow the basic idea from it.
No this will be a problem.
PHP Variable Functions
Depending on situation where you need this, maybe you can use anonymous functions like this:
$greet = function($name)
{
echo('Hello ' . $name);
};
$greet('World');
...then you can set new function to the given variable any time
A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file):
Main File:
<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>
Include File A:
<?php
if (!#$Override) {
function F1 () {echo "This is F1() in A";}
}
?>
Include File B:
<?php
function F1 () {echo "This is F1() in B";}
?>
Browsing to the main file displays "This is F1() in B".

test php functions (not classes) with netbeans and PHPUnit

I'd like to run unit test for a functions library file...
that is, I don't have a class, it's just a file with helper functions in it...
for example, I've created a php project at ~/www/test
and a file ~/www/test/lib/format.php
<?php
function toUpper( $text ) {
return strtoupper( $text );
}
function toLower( $text ) {
return strtolower( $text );
}
function toProper( $text ) {
return toUpper( substr( $text, 0, 1 ) ) . toLower( substr( $text, 1) );
}
?>
tools -> create PHPUnit tests gives me the following error:
PHPUnit 3.4.5 by Sebastian Bergmann.
Could not find class "format" in
"/home/sas/www/test/lib/format.php".
now, if I code (by hand!) the file
~/www/test/tests/lib/FormatTest.php
<?php
require_once 'PHPUnit/Framework.php';
require_once dirname(__FILE__).'/../../lib/format.php';
class FormatTest extends PHPUnit_Framework_TestCase {
protected function setUp() {}
protected function tearDown() {}
public function testToProper() {
$this->assertEquals(
'Sebastian',
toProper( 'sebastian' )
);
}
}
?>
it works fine, I can run it...
but if I select test file from format.php i get
Test file for the selected source file
was not found
any idea?
saludos
sas
ps: another question, is there a way to update generated tests without having to manually delete them???
ps2: using netbeans 2.8 dev
How you've written your Unit test case is 100% correct. The problem lies with common convention and how PHPUnit and Netbeans relies on them.
Best practice these days is to write all your code in an object orientated fashion. So instead of having a PHP file full of utility functions like you have, you wrap these functions into a class and have them as static functions. Here's an example using your code above,
<?php
class Format
{
public static function toUpper($text)
{
return strtoupper($text);
}
public static function toLower($text)
{
return strtolower($text);
}
public static function toProper($text)
{
return self::toUpper(substr($text, 0, 1 )) . self::toLower(substr($text, 1));
}
}
You'd now use your functions like so,
Format::toProper('something');
PHPUnit, and Netbeans, depend on this object orientated philosophy. When you try to automatically generate a PHPUnit test case, PHPUnit looks in your file for a class. It then creates a test case based on this class and it's public API, and calls it ClassNameTest, where ClassName is the name of the class being tested.
Neatbeans also follows this convention and knows that ClassNameTest is a PHPUnit test case for ClassName, so creates a link between the two in the IDE.
So, my advice is to always use classes where you can. If you have utility functions that don't depend on anything and are used globally, make them static ones.
Side note: I'd get rid of your two functions toUpper() and toLower(). There's no need to wrap built in PHP functions when there's no need to. There's also no need to test them as they are thoroughly tested.
Site note 2: There's kind of a built in PHP equivalent to your function toProper() called ucfirst().

Categories