On my phpunit tests I need to run a cleanup functionality for each test seperately for example:
use PHPUnit\Framework\TestCase;
use MyApp\Database\DatabaseEntryDataGenerator;
use MyApp\Database\Record\User;
use MyApp\Database\Record\Emails;
class MyEmailTest extends TestCase
{
public function testEmailValid()
{
/**
* #var EmailEntries
*/
$emails=DatabaseEntryDataGenerator::table(EmailEntries::TABLE)->generate();
//Do test
$emails->delete();
}
public function testEmailValidOnUser()
{
/**
* #var User
*/
$user=DatabaseEntryDataGenerator::table(User::TABLE)->generateSingle(1);
/**
* #var EmailEntries
*/
$emails=DatabaseEntryDataGenerator::table(EmailEntries::TABLE)->generateMultiple();
//Do test
$emails->delete();
$user->delete();
}
}
Assume that fictional DatabaseEntryDataGenerator generates data on database and the fictional EmailEntries and User represent the record data. The method delete on EmailEntries and User.
But if during the development of the test something brak mucase the delete that is the cleanup code may be deleted. Also the generic tearDown is way to generid and does not allow to specify a specific method indicain a test the required tearDown logic. For example in my case the teardown logic on testEmailValid id Different on testEmailValidOnUser and if something breakd for example due to a typo, may end up not be able to run it aall hence not giving me the test isolation.
So how I can have per-test specific tear down logic that will be executed regardless the test is successfull or not?
The only way to do this is by using seperate classes. If you are in need of different teardown logic per test, you are either having architectural issues, are testing different functionality or simply don't have a good enough teardown strategy.
Often times, simple truncate logic will suffice during the teardown logic.
I would suggest using database transaction here. You really want to do the same thing in both tests: rollback any changes made to the database.
public function setUp(): void
{
MyDatabaseClass:startTransaction();
}
public function tearDown(): void
{
MyDatabaseClass:rollback();
}
This way you won't need to have special logic for each test, and if you are affecting more tables than expected, you will still be safe.
Related
I have a class like this:
<?php
class Apple {
public function foo($arg1){
if ($arg1 == 0){
$this->bar($arg1);
}
}
public function bar($arg){
//do something
}
}
And I have a unit test like this:
class AppleTest extends TestCase{
/**
* it's unit test for method Apple::foo
*/
public function testFoo(){
$mock = $this->getMockBuilder('Apple')
->setMethods(['bar'])
->getMock();
$mock->expects($this->once())
->method('bar')
->with($this->equalTo(0));
$mock->foo(0);
}
}
I was told, that I can't use a mock for the class that is being tested. I was told that I should use instance of the class instead of its mock, because when I use mock it's not actual testing. Can some one argue with that.
It isn't that you "can't", but that you really shouldn't. Obviously from your example test, you can mock the object that you are testing.
But this isn't necessarily a good idea. The issue with this is that you are specifying exactly what the code should look like. This can make refactoring more difficult. Suppose that the bar function needs to change and you want to move the functionality the foo needs into a private function. Now your test will fail because foo is no longer calling bar. In this case, it should pass because the functionality hasn't changed. This is one of the great benefits of unit tests, you are able to refactor the code and ensure that things still work correctly.
However, there are times when it is necessary to mock the class that you are testing. Generally this is when you are trying to write new tests for existing code and you aren't able to refactor it to use dependency injection. Then you will have to mock the other function in order to isolate things. This isn't ideal and should be avoided but writing a "bad" test can be better than having no test at all.
Looking more into OOP and classes, I have an extremely large user class which is becoming increasingly large to manage. The total code is in excess of 950 lines and completely dismisses the Single Responsibility principle.
A few ways i thought to make this smaller is to create completely seperate classes and transfer the data in on the construction of the new class. For example:
index.php
$user = new user('username');
$userOptions = new userOptions($user);
or
$user = new user;
$userOptions = new userOptions;
$userOptions->setData(
$user->getData([
'username'=>'genericuser'
]),
);
However this seems un-natural and isn't as nice as i would expect properly formatted code to be.
Another way i thought of is to extend the base class into another one. For example:
index.php
$userOptions = new userOptions('username');
classes/useroptions.php
class userOptions extends User {
//a small section of what would be a big user class
}
However this also violates some PHP practices, with extends normally meaning a special case of which user options doesn't appear to be.
My final way of organising the document uses in the default class to seperate the large file down, for example:
classes/user.php
class User {
/**
* CREATION SECTION
*/
public function create() {
//create user
}
/**
* UPDATE SECTION
*/
public function change($whattochange) {
//what to change
}
}
However this once again seems to violate the single responsibility principle, with a lot of options being in one single class.
What is common practice to separate down a class, and how should it be done?
The current User class has the following methods inside of it:
* - $variables
* - __construct gets a new user.
* - stripeCustomer() gets the customer information if it exists
* - create($fields|array) method to create a new user
* - login($username|string, $password|string, $remember|bool) logs in a user
* - find ($param|string, $method|string) finds a user WHERE param=method
* - data() returns user data
* - isLoggedIn() returns whether a user is logged in
* - isAdmin() returns if a user is an admin
* - logout() logs out current user
* - displayName() returns first name or username
* - isVerified() checks if a user is verified
* - inCompany() checks if a user is in a company
* - inVerifiedCompany() checks if a user id in a verified company
* - verifyUser($apicode|string, $verification|string, $resend|bool) verifies a users email
* - error() returns any errors that may occur
* - getProfilePicture($size|int) gets a users profile picture from Gravatar with size of $size in pixels
* - passwordCheck($password|string) checks if two passwords match
*
* // 2FA section
* - has2FA() checks if the user has 2FA enabled
* - TOTP($type|string, $secret|string, $code|string, $backupcodes|array) everything to do with 2FA
* - countBackups() counts the amount of backup codes remaining for a user with 2FA
* - update($statement|string, $params|array, $apicode|string) updates a user
*
* // lockdown system
* - getAttempts() gets amount of attempts to break into a users account
* - isLocked() gets whether the user account is locked
* - addAttempt() adds an attempt to a users account
* - reinstateUser() unlocks a users account
* - shouldShowCaptcha() checks whether a captcha is needed
*
* // codes
* - sendRequest($code|int) sends a request to a users email with a specific code
* - verifyCode($code|string, $type|int) checks a user inputted code to one in the DB
*
* - deleteUser() deletes the specific user
* - makeAdmin() makes the user an admin
* - removeAdmin() removes the user as an admin
* - modify($changes|array, $apicode|string) modifies a user | no idea how this is different to update
I also understand that the database section of the class should be in a seperate mapper class, which would use the same style structure as my initial attempt, this will be changed soon.
Thanks in advance for all help.
For reference, i've had a look on google and found some people asking similar questions, however none seem to answer the question to a great degree.
How to break up a large class
there is a way which is called trait you can make any number of traits and include then in a class.. make seperate files of traits it will make your code easy to read..
What a trait actually is its like a class with lot of methods..
how to use it
the syntax will be something like this..
trait UserOptions{
public function create()
{
// logic goes here
}
public function destroy(){
// logic
}
}
trait UserAdmin{
public function isAdmin(){
return true;
}
}
class User{
// this is how to include traits
use UserOptions , UserAdmin ;
}
now all the methods of all the traits are included in the User class .
That is how we can break down so much of the code
Well, I am not really an expert myself. But I guess the answer to the question has two sides. One is not really technical. Let's start with it.
Refactoring is not a trivial task to do. Refactoring legacy code is twice so (I am not sure that your code is actually legacy one, but I guess the rule holds). Usually done by the people who are experts in their field. And even before they start there are a couple of steps to be done. Firstly, the current behaviour of the system must be documented. Either with some kind of end-to-end (acceptance) tests or by really thorough technical documentation (done by business analytics). Better with both. And only then you can start the process of rewriting. Without this, you simply cannot be sure the system will work as before. It the best case scenario, you will end up with explicit bugs (the ones you can clearly see right away). But you also can end up with some unexpected implicit behaviour, that you might notice only after some time.
Regarding technical side. Now you have so-called God object. It does at least persistence, authentication and authorization. So as you stated SRP (Single responsibility principle) is completely dismissed. So firstly you have to extract entity (business object):
final class User
{
private $id;
private $name;
// ...
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
public function id()
{
return $this->id;
}
public function name()
{
return $this->name;
}
}
Then extract repository to persist this entity:
final class UserRepository
{
/**
* \PDO or whatever connection you use.
*/
private $db;
public function __construct(\PDO $db)
{
$this->db = $db;
}
public function findByPk($id): User {}
public function create(User $user) {}
public function update(User $user) {}
public function delete(User $user) {}
}
Extract authentication and authorization into separate services. Even better, use existing packages (you can find many on GitHub).
But again all this is safe to do only if you have the way to ensure that your changes have not broken anything.
There is a book on the subject. To be honest, I have not read it myself yet, but I've listened to the podcast with the author and heard really good reviews. So you can check it out.
Instead of stitching rotten software you should think of a re-design with a migration process. The best is to create a new branch that can cope with old data structures but allows to introduce new (straight) ones. A clean cut is also better than many little migration steps. There's a risk in both: little step take long and each can cause user frustration. A cut can fail and you might need to roll back.
I must admit that I don't know if I have a problem in my design pattern, over-thinking or maybe even just class naming, so any suggestions are welcome. This must be an easy problem but it is rather hard for me to even explain it in words(language barrier), so I will try to do it in code.
For example I'm trying to iterate over a network data stream byte by byte(the task is completely irrelevant to question, just to better explain pseudo-code, please don't say that I use wrong tool to do that). Base class will look something like this:
class BaseNetworkIterator implements Iterator {
protected $stream;
protected $currentByte;
public function __construct() {
$this->stream = open_network_stream();
}
/** .... * */
public function next() {
$this->currentByte = $this->stream->getByte();
}
public function current() {
return $this->currentByte;
}
}
Now imagine that logic in this class is complicated by itself(not one line per method and there are many more helper methods) but I need to do even more. For example I need to reverse bits order in every byte. I don't want to include this logic in base class as it is already big, so I extend it:
class ReverseByte extends BaseNetworkIterator {
/** .... * */
public function next() {
parent::next();
$this->currentByte = $this->reverseStreamByte($this->currentByte);
}
protected function reverseStreamByte($byte) {
/** .... * */
}
}
And more, I want to completely skip all newlines in this stream(reversed):
class SkipNewLine extends ReverseByte {
/** .... * */
public function next() {
do {
parent::next();
} while ($this->currentByte === "\n");
}
}
And if we get two consecutive bytes(after all this operations - they may be separated by newlines etc.) equal to "NO", then we must reverse one following byte once more(don't think about it: just something that uses all previous logic and a protected method that was defined in one of the previous classes):
class HandleDoubleReverseKeyword extends SkipNewLine {
const DOUBLE_REVERSE_KEYWORD = 'NO';
/** .... * */
public function next() {
parent::next();
if ($this->getTwoCharsCache() === self::DOUBLE_REVERSE_KEYWORD) {
$this->currentByte = $this->reverseStreamByte($this->currentByte);
$this->clearTwoCharsCache();
} else {
$this->saveMaxTwoCharsCache($this->currentByte);
}
}
private function saveMaxTwoCharsCache($newChar) {
/** .... * */
}
private function getTwoCharsCache() {
/** .... * */
}
private function clearTwoCharsCache() {
/** .... * */
}
}
And now although logic is split between classes rather nicely for my taste(each consecutive class does something completely different and isolated and it is easy to see what is done in each layer) it is a mess to work with. If we add new "filter" in the middle we must change what later class is extended from... Naming starts to get insane as "HandleDoubleReverseKeyword" doesn't explain what this class really does even remotely (even if we are in "NetworkIterator" namespace). I don't really understand what a "final" class should look like.
I was thinking of using traits as naming goes much easier there but they cause more problems then solve(execution order, code completion etc.).
I was also thinking of using Yii-like "behaviour/event" pattern (Something like: base next() method consecutively calls an array of class/methods and some external source can add more class/methods to that array instead of extending base class) but there is a huge problem with properties/methods visibility(it is a problem, basically I have to make ALL properties and methods public) and more importantly it is not clear how to properly access methods of other additional classes.
Ok, this still may be not very clear so any feedback is appreciated. I know there is no question mark in this "question", but I hope my intentions are clear and the only thing that comes to mind is: how to do this type of design properly?
My 2 cents:
The stream should be separated from the iterator class and its sub classes. Iterator defines how to access the data, each iterator instance should only hold the reference to the data, not the actual data.
The logic in class HandleDoubleReverseKeyword is about how to process the data, not how to access the data; and the action is decided base on what the data is, so the class should not inherited from the iterator class; here I think we can use the state pattern.
So the code to deal with the stream could be like this:
$stream = open_network_stream();
$iterator it = new Iterator(&stream);
$data = it->next();
while(data){
switch(data->value){
case 'A': AcitionA->action();break;
case 'B': AcitionB->action();break;
}
$data = it->next();
}
I think you are approaching this from the wrong perspective.
The current hierarchy you have in place highly limits the re-usability of each component, since they are all implemented to work only on the result of a byte stream iterator. If for example you needed to implement a file iterator, and then skip over each new line, you cannot possibly reuse your existing SkipNewLine, because it works only on the result of a reverse byte iterator.
Another fallacy is that you have no way to control the order in which each of this steps occurred without rewriting the entire class structure. Even something as simply as moving the SkipNewLine class before the ReverseByte (or after the HandleDoubleReverseKeyword) is a refactoring nightmare.
I suggest you implement each step in the iteration as a separate class, that solely acts on a generic stream, and makes no assumptions as to the state of the source stream. You can inject an instance of each of these components into your BaseNetworkIterator, and use them independently of each other.
This will further provide you with the ability to act on each of the individual states with knowledge of the global state of the iteration.
I have a PHPUnit test case class (consisting of some test functions). I would like to write a oneTimeSetUp() function to be called once for all my tests in the class (unlike the standard setUp() function which is called once for each test in the class). In other words, I'm looking for a PHPUnit equivalent to the JUnit #BeforeClass annotation.
Same question with a oneTimeTearDown() function.
Is it possible to do so in PHPUnit?
Take a look at setUpBeforeClass() from section 6 of the PHPUnit documentation.
For the one time tearDown you should use tearDownAfterClass();.
Both this methods should be defined in your class as static methods.
setUpBeforeClass() is the way to do this if all of your tests are literally contained within a single class.
However, your question sort of implies that you may be using your test class as a base class for multiple test classes. In that case setUpBeforeClass will be run before each one. If you only want to run it once you could guard it with a static variable:
abstract class TestBase extends TestCase {
protected static $initialized = FALSE;
public function setUp() {
parent::setUp();
if (!self::$initialized) {
// Do something once here for _all_ test subclasses.
self::$initialized = TRUE;
}
}
}
A final option might be a test listener.
I came to this page with the same question, however the accepted answer is ran on all classes, and for me was not the correct answer.
If you are like me, your first "Integration test" is to clear out the DB, and run migrations. This gets yourself at a database baseline for all test. I am constantly changing migration files at this point, so setting up the baseline is truly part of all tests.
The migration takes a while, so I do not want it run on all tests.
Then I needed to build up the database testing each piece. I need to write an order test, but first I need to create some products and test that, then I need to test an import fuction.
So, what I did is SUPER easy, but not explained extremely well on the internet. I created a simple test to setup the database. Then in your phpspec.xml file add a testsuite....
<testsuite name="Products">
<file>tests/in/SystemSetupTest.php</file>
<file>tests/in/ProductTest.php</file>
<file>tests/in/ProductImportTest.php</file>
</testsuite>
And in the the SystemSetupTest.php ....
class SystemSetupTest extends ApiTester
{
/** #test */
function system_init()
{
fwrite(STDOUT, __METHOD__ . "\n");
self::createEM(); //this has all the code to init the system...
}
}
Then execute it like:
phpunit --testsuite Products
In the end, its a ton easier. It will allow me to build up my system correctly.
Additionally I am using laravel 5. When using setUpBeforeClass() I end up with bootstrap issues, which I am sure I can fix, but the method I use above works perfect.
The bootstrap option can be used on these cases.
You can call it from the command line
phpunit --bootstrap myBootstrap.php
Or put it in the XML file, like this:
<phpunit bootstrap="myBootstrap.php">
...
</phpunit>
Expanding on accepted answer:
None of the setUpBeforeClass(), tearDownAfterClass(), #beforeClass, #afterClass runs in the object context (static methods). You can work around that restriction by guarding any #before code with a static property instead, like so:
class MyTest extends PHPUnit\Framework\TestCase
{
private static $ready = false;
/**
* #before
*/
protected function firstSetUp()
{
if (static::$ready))
return;
/* your one time setUp here */
static::$ready = true;
}
}
It can't be used for #after, however, because there's no way of saying when the last test was called.
I'm using PHPUnit to test a class that has many functions.
The PHPUnit framework runs the test functions from the top to the bottom.
The question is: How can I run the test functions in a specified order without reorder then in the source code.
To clarify the issue, imagine we have 5 test functions;
testFunc1
testFunc2
testFunc3
testFunc4
testFunc5
The framework will run testFunc1 then testFunc2 until it reaches testFunc5.
However, I want to run testFunc3 then testFunc1 then testFunc5 then testFunc2 then testFunc4 without reordering them in the source file.
PHPUnit will execute the tests in the exact order they are written in your *_TestCase class.
Every one of those tests should be able to run in isolation and not depend on some other test beeing executed before it.
If you have issues testing against a Database I'd suggest using somethig like this:
class MyTest extends PHPUnit_Framework_TestCase {
public function setUp() {
// REPLACE INTO testDb (ID, NAME, VALUE) VALUES (1001000, 'testing', 'value')
$this->db = $db_connection;
}
public function tearDown() {
// DELETE FROM testDb WHERE ID > 10010000 // or something like this
}
public function testSelect() {
$this->assertSame("value", $this->db->getId(100100));
}
/**
* #depends testSelect
*/
public function testInsert() {
$this->db->insertById(1001111, "mytest", "myvalue");
$this->db->getId(1001111);
}
/**
* #depends testSelect
*/
public function testDelete() {
$this->db->deleteById(1001000);
$this->assertNull($this->db->getId(10010000);
}
// and so on
}
The setUp() method will be run before every testcase and make sure all the values most testcases need are there, the tearDown() will clean up after the testsuite.
The #depends annotation will make sure that the insert test isn't run when the select test fails. (If you can't load values then inserting new ones and getting those can't work ether, no need to try it).
For that also check the manual on test dependencies
The whole point of unit tests are actually in the name itself, Unit Testing. They function on their own and have no dependencies whatsoever on each other. If you code your tests right, order of execution should not matter.
If it is a matter of a database issue, make sure you have a clean database before every test.
Right now there's no way to do it short of reordering the functions in the file. There's a feature request to use the #depends annotations to reorder the tests, and the PHPUnit author has expressed a desire to do it. You can comment on the request at PHPUnit's github tracker.