I'm currently trying to write some basic unit tests for a php application, unfortunately the test always succeed, even if i want them to fail. I googled for many hours, but without success. Below you can find the code which succeeds on every call:
public function testCreateArticle()
{
$articleRepository = RepositoryFactory::getArticleRepository();
$this->fail();
}
Test succeeds.
If I switch the statements (fail() first) the test fails, but since I need the articleRepository, I can't do any asserts at all. It just seems to return a success after the first line.
Does anyone have a clue what could be wrong?
Related
A bit unclear on the title, but here we go.
I am running a unit test on a method that essentially runs a strpos(). Like this:
return strpos($this->getHeaderLine($headerName), $value) !== false;
Now I also want to see what happens if I supply it an empty value. When provide an empty string, I get the following message:
strpos(): Empty needle
This message in itself is clear enough, I don't want to throw an exception here. I do want to know if it returned this message though. How would I go about doing this or do I need to rewrite my method?
Try the following:
public function testWarning()
{
$this->expectException(PHPUnit_Framework_Error_Warning::class);
$this->expectExceptionMessage("Empty needle");
strpos('meh', '');
}
This test passes, but if you comment out the expectations, it fails. There are more related classes in PHPUnit framework, like PHPUnit_Framework_Error_Deprecated, PHPUnit_Framework_Error_Notice and so on.
I have a static method named ServerResponse that basically shows a message whether on success or fail. I just want to know the proper way to actually display the message and exit the script.
Should I implement my method like this:
public static function ServerResponse($e,$m){
print(json_encode([$e,$m]));
exit;
}
//Sample use:
if(this happens){
myclass::ServerResponse($x,$y);
}
or like this:
public static function ServerResponse($e,$m){
return json_encode([$e,$m]);
}
//Sample use:
if(this happens){
print(myclass::ServerResponse($x,$y));
exit;
}
Which one is proper and better... and why?
is there any difference between them? (on execution time).
"Don't be hard on me I am not an expert (just yet)..."
For better debugging, it's advised to always make a function or method return a value. So your 2nd sample should be chosen.
exit (or die) are commonly used when the program ends with an error, giving the ability to add an exit status (as a number or a string).
I suppose there will be no significant difference about the execution time.
I don't know if this is common practice but I only use exit to debug. If your script comes to the end of execution it will exit on it's own.
If you must exit, do it in the main script, not in a function.
functions should have one task and do that task. So the function ServerResponse should send a response and not kill the script.
I have a couple of really basic tests written in PHPUnit and for some reason when I enable one of the assertions, I get "No Tests Executed."
I'm not a skilled unit tester, so it's clearly something I'm doing wrong, but I'm having a hard time tracking down a solution.
I'm testing for a string coming back from a Soap server it's either "true" or "false."
In my unit test if I write this
$hasErrors = 'false';
$this->assertTrue('true' == $hasErrors);
I get "No tests executed!"
If I do the following - I know it's not the same test but it is successful and PHPUnit reports it as successful - I'm just curious why this one runs the tests, while that previous doesn't just show a failure but says no test are executed.
$hasErrors = 'false';
$this->assertFalse('true' == $hasErrors);
I would like the failure to fail rather say "No tests executed."
The same thing happens if I use assertNotEquals rather than assertFalse.
More information. I might have stumbled across a phpunit bug when dealing with a text string "true." I think php unit is wanting to treat it as a boolean rather than a string. So I made some code changes to work with booleans.
$result = $xmlresponse->xpath('//result');
$hasErrors = (string) $result[0]->hasErrors;
if ($hasErrors == 'true') {
$errors = TRUE;
} else {
$errors = FALSE;
}
$this->assertFalse($errors);
Now I get.
PHP Fatal error: Uncaught Failed asserting that true is false.
Why do I need to "catch" this failed asserting? Shouldn't phpunit just report that the test failed?
I'm executing phpunit like this from cli.
phpunit --verbose --debug --configuration testSuite.xml
testSuite.xml looks like this:
<phpunit>
<testsuites>
<testsuite name="connector">
<file>TestNewAccount.class.php</file>
<file>TestModifyAccount.class.php</file>
</testsuite>
</testsuites>
</phpunit>
Update
So I guess my expectations of what PHPunit does out the box are not valid. I expected that phpunit would run the tests, report success and failures and that's that. But apparently it reports successes and throws fatal exceptions on an assertion failure. I don't understand why it's so heavy handed with failures and why it doesn't simply report the failure without me having to catch exceptions in my tests and handle it on my own.
I'm sure I'm still missing something, but for now, I'm not super impressed with phpunit out of the box. I guess it works but it seems to make me work harder than I want to in order to write a few simple tests and assertions.
Update 2
So I'm getting the response from phpunit that I was originally expecting. Now the failures are reporting as failures. I'm not sure what I'm doing differently now than I was before. Now I feel like I'm just cluttering up Stackoverflow with my own senseless rambling. Thanks for the help.
It's good practice to use a quite specific test - assertNotEquals('x', 'y') rather than assertFalse('x'=='y') - having to think about one thing is better than having to then also translate that to a different condition.
When I create a new test class, I tend to put a couple of sanity-checks in, to make sure the test itself is being run, something as simple and obviously failing as 'assertTrue(false)'. If that doesn't fail - then there is something very wrong going on. I've often found it to be name (even upper/lower-case) related.
To debug what is going on, I'd try to get down to the simplest, smallest possible that that does not do what you expect. Debug it from there, or have someone else take a look. The "other person" could equally be a Rubber Duck that you talk it through to, step, by step.
I figured this out. It had nothing to do with PHPUnit as I began to suspect. There's just no way this is only happening to me and it be PHPUnit's fault. I'm doing anything remarkable with PHPUnit.
The problem was that I am making curl calls that had too short of a timeout set. The timeout was set to 10 seconds, but the service I was hitting needed like 2 minute wait times from time-to-time (it's a machine-to-machine sort of thing, so not a huge deal). The short timeout was being hit and PHPUnit would report No Tests Executed!
I am writing a PHPUnit test suite and have run into a bit of a problem.
Here is the test:
public function testSomething(){
$stub = $this->getMockForAbstractClass('\core\classes\ImportedFile');
$stub->expects($this->exactly(4))
->method('thismethoddoesntexist');
$this->markTestIncomplete('not finished implementing');
}
For some reason this test is not failing. It should because the method does not exist and is therefore not called even once, let alone 4 times. It doesn't matter what I put in there, even if I put in a method name that does exist and say that I'm expecting it to run 100,000 times it still passes when this is obviously wrong.
I find this very strange since I have similar checks in previous tests which work properly.
Has anyone else experienced problems like this?
markTestIncomplete throw special exception, witch end the test. Checks for 'expects' in mocks are skipped.
public static function markTestIncomplete($message = '')
{
throw new PHPUnit_Framework_IncompleteTestError($message);
}
Found the cause of the problem. It seems to be caused by the call to $this->markTestIncomplete(). For some reason having this in the test causes it not to fail, at least in this case, even when it should.
Removing the call to markTestIncomplete makes it behave normally and fail when it should. I tend to leave the markTestIncomplete method in a test until it is 100% complete, and assume that if I run the test, even in its incomplete state, it should fail if an expectation is not met. Is this not a fair assumption to make? Is this a bug in PHPUnit?
Is it possible to mark a test as "expected to fail" with PHPUnit? This would be useful when performing TDD, and you want to distinguish between genuinely failed tests, and tests that happen to fail because the associated code hasn't been written yet.
I think in these cases, it's fairly standard to simply mark the test as skipped. Your tests will still run and the suite will pass, but the test runner will alert you of the skipped tests.
http://phpunit.de/manual/current/en/incomplete-and-skipped-tests.html
The 'correct' method of handling this is to use $this->markTestIncomplete(). This will mark the test as incomplete. It will come back as passed, but it will display the message provided. See http://www.phpunit.de/manual/3.0/en/incomplete-and-skipped-tests.html for more information.
I really think it's a bad practice, however you can trick PHPUnit this way:
/**
* This test will succeed !!!
* #expectedException PHPUnit_Framework_ExpectationFailedException
*/
public function testSucceed()
{
$this->assertTrue(false);
}
More cleanly:
public function testFailingTest() {
try {
$this->assertTrue(false);
} catch (PHPUnit_Framework_ExpectationFailedException $ex) {
// As expected the assertion failed, silently return
return;
}
// The assertion did not fail, make the test fail
$this->fail('This test did not fail as expected');
}
The comment by sixty-nine above is nearly perfect for what I was searching for.
The fail() method is useful for when you set a test for an expected exception and if it did not trigger the exception you want the test to fail.
$this->object->triggerException();
$this->fail('The above statement was expected to trigger and exception.');
Of course the triggerException is replaced by something in your object.
If you want to have a test fail but know that its failure was expected, you can add a message to the assertion that will output in the results:
public function testExpectedToFail()
{
$this->assertTrue(FALSE, 'I knew this would happen!');
}
In the results:
There was 1 failure:
1) testExpectedToFail(ClassTest)
I knew this would happen!
In PHPUnit 8.2.5 you can simply expect the thrown assertion exception:
$this->expectException('PHPUnit\Framework\ExpectationFailedException');
$this->assertTrue(false);