I am following the examples in the PHPUnit manual. See the two Test files below. I am running the tests in Eclipse PDT with PTI installed. I see the following problems:
When running DependencyFailureTest, it does not recognize it as being a test. Is does not run anything.
When running MultipleDependenciesTest, it is running and mentions that all three test cases pass, as it should. However, if I then change the expected outcome in the function testConsumer into array('first', 'third'), it still mentions that all test cases pass, although one of them should clearly fail. Also, when I change one of the assertions into $this->assertTrue(FALSE);, I expect a failed and a skipped test case, but again all test cases pass.
Has anyone experienced something similar, and solved this?
DependencyFailureTest
<?php
class DependencyFailureTest extends PHPUnit_Framework_TestCase
{
public function testOne()
{
$this->assertTrue(FALSE);
}
/**
* #depends testOne
*/
public function testTwo()
{
}
}
?>
MultipleDependenciesTest
<?php
class MultipleDependenciesTest extends PHPUnit_Framework_TestCase
{
public function testProducerFirst()
{
$this->assertTrue(true);
return 'first';
}
public function testProducerSecond()
{
$this->assertTrue(true);
return 'second';
}
/**
* #depends testProducerFirst
* #depends testProducerSecond
*/
public function testConsumer()
{
$this->assertEquals(
array('first', 'second'),
func_get_args()
);
}
}
?>
I don't have a good answer yet, only some black magic voodoo. I noticed that for running it in the command line, I need to include the class under test.
<?php
require_once ('path/to/Car.php')
class CarTest extends PHPUnit_Framework_TestCase {
...
For running it in PTI, I mention the file in the Bootstrap file in the PHPUnit preferences. Therefore, this reuire_once statement is not necessary. But worse however, this require_once statement causes the test not to run!
Something strange that I noticed is that at one time, my tests were not running, even without the require_once statement. In the PHPUnit preferences, I had the option Do not check for equal namespaces while searching for php/test case classes enabled. I disabled it, and it worked. I enabled it again, and it still worked.
Phpunit doesnot show any thing (run 0/0)
Console Error:
Fatal error: Declaration of PHPUnitLogger::addFailure(Test $test, AssertionFailedError $e, $time): void must be compatible with PHPUnit\Framework\TestListener::addFailure(PHPUnit\Framework\Test
$test, PHPUnit\Framework\AssertionFailedError $e, float $time): void in
C:\Users\xxx\AppData\Local\Temp\phpunit_printer\PHPUnitLogger.php(415): eval()'d code on line 1
TestCase
<?php
namespace PHPUnit\Framework;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
class SeleniumTest extends \PHPUnit_Framework_TestCase
{
protected $webDriver;
public function setUp()
{
// system . property_exists("Facebook\WebDriver\Firefox\FirefoxDriver", "C:\rc\geckodriver\geckodriver");
// System . set("Webdriver.gecko.driver", "C:\rc\geckodriver\geckodriver");
$this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', DesiredCapabilities::firefox());
$this->webDriver->manage()
->window()
->maximize();
$this->webDriver->get('http://localhost/farmer/login');
// $this->webDriver->get("www.gmail.com");
}
public function testLoginPass()
{
$this->webDriver->get('http://localhost/farmer/login');
$this->webDriver->findElement(WebDriverBy::name('username'))->sendKeys(' correct');
$this->webDriver->findElement(WebDriverBy::id('password'))->sendKeys('password');
$this->webDriver->findElement(WebDriverBy::name('btn-login'))->click();
$content = $this->webDriver->findElement(WebDriverBy::tagName('body'))->getText();
$this->assertContains('Dashboard', $content);
}
public function testLoginFail()
{
$this->webDriver->get('http://localhost/farmer/login');
$this->webDriver->findElement(WebDriverBy::name('mobile'))->sendKeys("800000000000");
$this->webDriver->findElement(WebDriverBy::id('password'))->sendKeys("8000000000");
$this->webDriver->findElement(WebDriverBy::name('btn-login'))->click();
$content = $this->webDriver->findElement(WebDriverBy::className('help-block'))->getText();
$this->assertContains('Your Credential Doesnot Match.Please Try Again !!', $content);
}
public function tearDown()
{
$this->webDriver->quit();
}
}
?>
While MakeGood is working Properly in Eclipse (Everything is OK)
MAKEGOOD result
Related
I'm trying to override a built in php function using a namespaced test like this:
Original Class:
<?php
namespace My\Namespace;
class OverrideCommand
{
public function myFileExists($path)
{
return file_exists($path);
}
}
Unit Test
<?php
namespace My\Namespace\Test\Unit\Console\Command;
function file_exists($path)
{
return true;
}
class OverrideCommandTest extends \PHPUnit_Framework_TestCase
{
/**
* #var OverrideCommand
*/
protected $command;
protected function setUp()
{
$this->command = new \My\Namespace\OverrideCommand();
}
public function testMyFileExists()
{
$result = $this->command->myFileExists('some/path/file.txt');
$this->assertTrue($result);
}
}
In this case the file_exists function in my test should always return true, however when I run PHPUnit I get:
PHPUnit 5.7.21 by Sebastian Bergmann and contributors.
There was 1 failure:
1) My\Namespace\Test\Unit\Console\Command\OverrideCommandTest::testMyFileExists
Failed asserting that false is true.
It's as if the namespaced function is being ignored and it's just calling the built in function instead, am I missing something?
According to your code sample, you define the function file_exists() in the namespace My\Namespace\Test\Unit\Console\Command:
namespace My\Namespace\Test\Unit\Console\Command;
function file_exists($path)
{
return true;
}
so of course, you actually never override the function file_exists() in the root namespace.
As far as I know, you can't do that. Whenever you would try to define a function that already exists, a fatal error will be triggered, see https://3v4l.org/JZHcp.
However, if what you want to achieve is asserting that OverrideCommand::myFileExists() returns true if a file exists, and false if it doesn't, you can do one of the following
Refer to files which do and do not exist in your test
public function testMyFileExistsReturnsFalseIfFileDoesNotExist()
{
$command = new OverrideCommand();
$this->assertTrue($command->myFileExists(__DIR__ . '/NonExistentFile.php');
}
public function testMyFileExistsReturnsTrueIfFileExists()
{
$command = new OverrideCommand();
$this->assertTrue($command->myFileExists(__FILE__);
}
Mock the file system
Use https://github.com/mikey179/vfsStream to mock the file system.
Note: For your example, I would recommend the former.
I am trying to test methods from the following class I have written (there are more functions than what is shown, basically, one function for each is_*() method):
class Validate {
private static $initialized = false;
/**
* Construct won't be called inside this class and is uncallable from the outside. This prevents
* instantiating this class. This is by purpose, because we want a static class.
*/
private function __construct() {}
/**
* If needed, allows the class to initialize itself
*/
private static function initialize()
{
if(self::$initialized) {
return;
} else {
self::$initialized = true;
//Set any other class static variables here
}
}
...
public static function isString($string) {
self::initialize();
if(!is_string($string)) throw new InvalidArgumentException('Expected a string but found ' . gettype($string));
}
...
}
When I test if the methods throw an exception on invalid input, it works great! However, when I test if the method works as expected, PHPUnit complains because I have no assert in the test. The specific error is:
# RISKY This test did not perform any assertions
However, I don't have any value to assert against so I'm not sure how to overcome this.
I've read some about testing static methods, but that mostly seems to cover dependencies between static methods. Further, even non-static methods could have no return value, so, how to fix this?
For reference, my test code:
class ValidateTest extends PHPUnit_Framework_TestCase {
/**
* #covers ../data/objects/Validate::isString
* #expectedException InvalidArgumentException
*/
public function testIsStringThrowsExceptionArgumentInvalid() {
Validate::isString(NULL);
}
/**
* #covers ../data/objects/Validate::isString
*/
public function testIsStringNoExceptionArgumentValid() {
Validate::isString("I am a string.");
}
}
Test void function with assertNull:
/**
* #covers ../data/objects/Validate::isString
*/
public function testIsStringNoExceptionArgumentValid() {
$this->assertNull( Validate::isString("I am a string.") );
}
To prevent the warning about the assertions you can use the #doesNotPerformAssertions annotation as explained in the documentation: https://phpunit.de/manual/current/en/appendixes.annotations.html#idp1585440
Or if you prefer code over annotation:
$this->doesNotPerformAssertions();
One solution I have come upon is the following, based on example 2.12 from chapter 2 of PHPUnit. It feels a little hacky to me, but it's the best I've found so far. Also, based on this PHPUnit Gitub issue discussion, it seems several other people want this feature but that there are no plans to implement it.
Change testIsStringNoExceptionArgumentValid() to the following:
/**
* #covers ../data/objects/Validate::isString
*/
public function testIsStringNoExceptionArgumentValid() {
try {
Validate::isString("I am a string.");
} catch (InvalidArgumentException $notExpected) {
$this->fail();
}
$this->assertTrue(TRUE);
}
If you want to test a void function you only need to run it without any assertion.
If it there is any issue it will throw an exception and test will fails. No need to put $this->assertTrue(TRUE); as you are not running an assertion and having assertions is not required to test your code.
You will get a message like
Time: 7.39 seconds, Memory: 16.00 MB
OK (1 test, 0 assertions)
Process finished with exit code 0
I have the below code, which I would expect to fail when run as the class DoesNothing doesn't use the mock class or call any of the required methods on it.
<?php
class DoesNothing
{
}
class DoesNothingTest extends YourMockeryTestCase
{
/**
* #test
*/
public function somethingIsCalled()
{
$this->mock = Mockery::mock();
$keys = array(
'1234',
'abcxyz',
'*&(%&^$-*/~#:{}',
')*&GA^FAUIB(*',
'',
' ',
);
foreach ($keys as $key) {
$this->mock
->shouldReceive('remove')
->atLeast()->times(1)
->with($key);
}
$var = new DoesNothing($this->mock);
}
}
But when I run it, it passes. I would expect it to say "method remove was not called" etc.
What could be wrong? Something to do with how Mockery Talks to PHPUnit?
Thanks,
Martin
Edit:
I shoudl also mention we are using Etsy's PHPExtensions to integrate it into PHPUnit
Your method name should start with test, otherwise PHPUnit will not determine it as test.
public function testSomethingIsCalled()
edit
You have to call Mockery::close() in your teardown method for expectations to be executed. i.e.
/**
* Tear down
*/
public function tearDown()
{
\Mockery::close();
}
I have written some test cases and want to try them out with PHPUnit. However, it does not work.
If I run phpunit CategoryTest it outputs:
PHPUnit 3.7.14 by Sebastian Bergmann.
If I do phpunit --log-json error.log CategoryTest, error.log file displays:
{"event":"suiteStart","suite":"CategoryTest","tests":5}
{"event":"testStart","suite":"CategoryTest","test":"CategoryTest::test__construct"}
So, it finds that there are 5 tests in the file, starts doing the first one and for no reason stops. Is there any log where I could find a reason why it would not continue execution?
Also, if I run test on some other file, say phpunit --log-json error.log UserTest, the shell does not display any output and neither does error.log file.
I tried reinstalling it, as it was suggested in one of the other similar questions, but it didn't do anything.
Any ideas how I could fix it?
require_once '../Category.class.php';
require_once '../../db_connect.php';
require_once 'PHPUnit/Framework/TestCase.php';
class CategoryTest extends PHPUnit_Framework_TestCase {
private $Category;
protected function setUp() {
parent::setUp ();
$this->Category = new Category(0, $mdb2);
}
protected function tearDown() {
$this->Category = null;
parent::tearDown ();
}
public function __construct() {
}
public function test__construct() {
$this->markTestIncomplete ( "__construct test not implemented" );
$cat = $this->Category->__construct(0, $mdb2);
$this->assertInstanceOf('Category', $cat);
}
public function testReturnID() {
$this->markTestIncomplete ( "returnID test not implemented" );
$id = $this->Category->returnID();
$this->assertEquals(0, $id);
}
...
}
Variable $mdb2 comes from the db_connect.php file.
I figured it out. The problem was that I included a variable from outside of a class.
You shouldn't overwrite the __construct() method in your TestCase. The constructor sets up the mock generator and some other mandatory thing for the test, so you get a lot of strange behaviour and unwanted side effects if you overwrite the constructor. The setUp() method is the special method you should use to initialize your test.
I'm having difficulty mocking the PDO object with PHPUnit.
There doesn't seem to be much information on the web about my problem but from what I can gather:
PDO has 'final' __wakeup and
__sleep methods that prevent it from being serialised.
PHPunit's mock object implementation serialises the object at some point.
The unit tests then fail with a PHP error generated by PDO when this occurs.
There is a feature meant to prevent this behavior, by adding the following line to your unit test:
class MyTest extends PHPUnit_Framework_TestCase
{
protected $backupGlobals = FALSE;
// ...
}
Source: http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
This isnt working for me, my test still produces an error.
Full test code:
class MyTest extends PHPUnit_Framework_TestCase
{
/**
* #var MyTest
*/
private $MyTestr;
protected $backupGlobals = FALSE;
/**
* Prepares the environment before running a test.
*/
protected function setUp()
{
parent::setUp();
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
parent::tearDown();
}
public function __construct()
{
$this->backupGlobals = false;
parent::__construct();
}
/**
* Tests MyTest->__construct()
*/
public function test__construct()
{
$pdoMock = $this->getMock('PDO', array('prepare'), array(), '', false);
$classToTest = new MyTest($pdoMock);
// Assert stuff here!
}
// More test code.......
Any PHPUnit pro's give me a hand?
Thanks,
Ben
$backupGlobals does not help you, because this error comes from elsewhere. PHPUnit 3.5.2 (possibly earlier versions as well) has the following code in PHPUnit/Framework/MockObject/Generator.php
if ($callOriginalConstructor &&
!interface_exists($originalClassName, $callAutoload)) {
if (count($arguments) == 0) {
$mockObject = new $mock['mockClassName'];
} else {
$mockClass = new ReflectionClass($mock['mockClassName']);
$mockObject = $mockClass->newInstanceArgs($arguments);
}
} else {
// Use a trick to create a new object of a class
// without invoking its constructor.
$mockObject = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($mock['mockClassName']), $mock['mockClassName']
)
);
}
This "trick" with unserialize is used when you ask getMock to not execute the original constructor and it will promptly fail with PDO.
So, how do work around it?
One option is to create a test helper like this
class mockPDO extends PDO
{
public function __construct ()
{}
}
The goal here is to get rid of the original PDO constructor, which you do not need. Then, change your test code to this:
$pdoMock = $this->getMock('mockPDO', array('prepare'));
Creating mock like this will execute original constructor, but since it is now harmless thanks to mockPDO test helper, you can continue testing.
The best I can think of is to use runkit and redefine the two final methods as protected using runkit_function_redefine.
Dont for get to enable the runkit.internal_override setting in php.ini.
And as ever, as with eval, if runkit seems like the answer, the question is probably wrong :)
You are instantiating your test case in your test case?
$classToTest = new MyTest($pdoMock);
Right now, you are essentially testing your test case. It should be more something like:
$classToTest = new My($pdoMock);