I am new to PHP and trying to write a basic test case that verifies a connection to a database. Clearly I'm missing something fundamental. I understand from reading the manual online that this involves extending the PHPUnit_Extensions_Database_TestCase and implementing a couple of functions (getConnection() and getDataSet()). Please see my code below of the simplest case I could come up with to still get the head-scratching issue I'm encountering:
<?php
abstract class DBTest extends PHPUnit_Extensions_Database_TestCase
{
public function getConnection()
{
return true;
}
public function getDataSet()
{
return true;
}
}
?>
As you can see, the tests do nothing but return true. However, when I do a "phpUnit DBTest" I get the following message back:
PHPUnit 4.2.6 by Sebastian Bergmann.
F
Time: 1 ms, Memory: 7.50Mb
There was 1 failure:
1) Warning
No tests found in class "DBTest".
FAILURES!
Tests: 1, Assertions: 0, Failures: 1.
What am I missing? Any advice would help. Thanks.
PHPUnit complains about not finding any test. You must add at least a test method:
<?php
abstract class DBTest extends PHPUnit_Extensions_Database_TestCase
{
public function getConnection()
{
return true;
}
public function getDataSet()
{
return true;
}
public function testDummy()
{
$this->assertTrue(true);
}
}
?>
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 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
I am not sure if I am doing something wrong or it is a bug with PHPUnit and mock objects. Basically I am trying to test if $Model->doSomething() is called when $Model->start() is triggered.
I am using Ubuntu in a VirtualBox, and phpunit 1.1.1 installed via pear.
The full code is below. Any help would be appreciated, it's driving me crazy.
<?php
require_once 'PHPUnit/Autoload.php';
class Model
{
function doSomething( ) {
echo 'Hello World';
}
function doNothing( ) { }
function start( ) {
$this->doNothing();
$this->doSomething();
}
}
class ModelTest extends PHPUnit_Framework_TestCase
{
function testDoSomething( )
{
$Model = $this->getMock('Model');
$Model->expects($this->once())->method('start'); # This works
$Model->expects($this->once())->method('doSomething'); # This does not work
$Model->start();
}
}
?>
The output from PHPUnit:
There was 1 failure:
1) ModelTest::testDoSomething
Expectation failed for method name is equal to <string:doSomething> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
As you found, you need to tell PHPUnit which methods to mock. Also, I would avoid creating expectations for methods that you are calling directly from the test. I would write the above test like this:
function testDoSomething( )
{
$Model = $this->getMock('Model', array('doSomething');
$Model->expects($this->once())->method('doSomething');
$Model->start();
}
Just to expand on why David Harkness's answer works, if you do not specify the $methods parameter to getMock then all functions in the class are mocked. Incidentally, you can confirm this with:
class ModelTest extends PHPUnit_Framework_TestCase
{
function testDoSomething( )
{
$obj = $this->getMock('Model');
echo new ReflectionClass(get_class($obj));
...
}
}
So, why does it fail? Because your start() function has been mocked too! I.e. the function body you have given has been replaced, and so your $this->doSomething(); line never gets run.
Hence, when there are any functions in your class that you need to be preserved, you'll have to explicitly give the list of all other functions.
I use a class to execute a testsuite with PhpUnit like :
$suite = new PHPUnit_Framework_TestSuite('PHPUnit Framework');
$suite->addTestSuite('ClassOne');
$suite->addTestSuite('ClassTwo');
return $suite;
To start the unit test :
# phpunit --stop-on-failure TestSuite.php
If "ClassOne" has an error or exception, the test continue with "ClassTwo".
How I could stop all the testsuites if the first test failed?
Works with PHPUnit 3.5.14
Using the code below the outputs are as expected:
Two fails running it normally:
phpunit AllTests.php
PHPUnit 3.5.14 by Sebastian Bergmann.
FF
Time: 0 seconds, Memory: 6.25Mb
There were 2 failures:
1) Framework_AssertTest::testFails
Failed asserting that <boolean:true> matches expected <boolean:false>.
/home/edo/test/AllTests.php:7
2) Other_AssertTest::testFails
Failed asserting that <boolean:true> matches expected <boolean:false>.
/home/edo/test/AllTests.php:13
FAILURES!
Tests: 2, Assertions: 2, Failures: 2.
and one fail running it with --stop-on-failure
phpunit --stop-on-failure AllTests.php
PHPUnit 3.5.14 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 6.25Mb
There was 1 failure:
1) Framework_AssertTest::testFails
Failed asserting that <boolean:true> matches expected <boolean:false>.
/home/edo/test/AllTests.php:7
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
AllTests.php
<?php
class Framework_AssertTest extends PHPUnit_Framework_TestCase {
public function testFails() {
$this->assertSame(false, true);
}
}
class Other_AssertTest extends PHPUnit_Framework_TestCase {
public function testFails() {
$this->assertSame(false, true);
}
}
class Framework_AllTests
{
public static function suite()
{
$suite = new PHPUnit_Framework_TestSuite('PHPUnit Framework');
$suite->addTestSuite('Framework_AssertTest');
$suite->addTestSuite('Other_AssertTest');
return $suite;
}
}
class Other_AllTests
{
public static function suite()
{
$suite = new PHPUnit_Framework_TestSuite('PHPUnit Framework');
$suite->addTestSuite('Other_AssertTest');
return $suite;
}
}
class AllTests
{
public static function suite()
{
$suite = new PHPUnit_Framework_TestSuite('PHPUnit');
$suite->addTest(Framework_AllTests::suite());
return $suite;
}
}
As a side node. If you look at the documentation of the current version only "suites by file system" and "suites by xml config" are explained options. Just to keep that in mind if you can migrate at the point.
Sounds like a bug in phpunit. Upgrade phpunit to the latest version. If that does not help, open a bug report.
In my TDD project I am trying to test a method in an abstract class.
abstract class Database_Mapper_Abstract
{
public function setTable($sTablename){
return('foo');
}
}
This is the way I wrote my simple test:
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$oMock->expects($this->once())
->method('setTable')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$this->assertEquals('foo',$oMock->setTable());
}
When I run this test i get the following error:
PHPUnit 3.5.13 by Sebastian Bergmann.
E
Time: 1 second, Memory: 6.75Mb
There was 1 error:
1)
Database_Mapper_AbstractTest::testCanSetTable
Missing argument 1 for
Database_Mapper_Abstract::setTable(), called in
K:\xampp\htdocs\tests\library\Database\Mapper\Abstract.php
on line 15 and defined
K:\xampp\htdocs\library\Database\Mapper\Abstract.php:4
K:\xampp\htdocs\tests\library\Database\Mapper\Abstract.php:15
FAILURES! Tests: 1, Assertions: 0,
Errors: 1.
The way I understand this is that it can't find the argument for the setTable function.
But I set it with the with() method. I also tried with('foo'). That also doesn't help me.
Does anyone have an idea?
Testing an abstract class:
For testing an abstract class you don't want to use the "create behavior methods".
Just getMockForAbstractClass() like this:
<?php
abstract class JCMS_Database_Mapper_Abstract
{
public function setTable($sTablename){
return $sTablename."_test";
}
}
class myTest extends PHPUnit_Framework_TestCase {
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$this->assertEquals('foo_test', $oMock->setTable('foo'));
}
}
You just use the mocking functionality to create an instance of that abstract class and test against that.
It's only a shortcut for writing
class MyDataMapperAbstractTest extends JCMS_Database_Mapper_Abstract {
// and filling out the methods
}
The actual error:
What happens is that you have a method with one parameter:
public function setTable($sTablename){
but you call it with zero paremters:
$oMock->setTable()
so you get an error from PHP and if PHP throws a warnings PHPUnit will show you an error.
Reproduce:
<?php
abstract class JCMS_Database_Mapper_Abstract
{
public function setTable($sTablename){
return('foo');
}
}
class myTest extends PHPUnit_Framework_TestCase {
public function testCanSetTable(){
$oMock = $this->getMockForAbstractClass('JCMS_Database_Mapper_Abstract');
$oMock->expects($this->once())
->method('setTable')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$this->assertEquals('foo',$oMock->setTable());
}
}
Results in:
phpunit blub.php
PHPUnit 3.5.13 by Sebastian Bergmann.
E
Time: 0 seconds, Memory: 3.50Mb
There was 1 error:
1) myTest::testCanSetTable
Missing argument 1 for JCMS_Database_Mapper_Abstract::setTable(), called in /home/.../blub.php on line 19 and defined
Fixing
Change:
$this->assertEquals('foo',$oMock->setTable());
to
$this->assertEquals('foo',$oMock->setTable('foo'));
then you don't get a PHP Warning and it should work out :)