Hi Dieter,
I almost reduce the use of super global variables inside functions of
PMA_DisplayResults class. Most of the fields are set while executing the getTable() function
since
they cannot set while executing the constructor.
Now I'm move into writing tests. I am facing to a problem with writing tests. How can I access or set the private variables, by a test ? The already existed tests also failing due to this change. Your suggestions will very helpful.
I didn't have a look at the current tests and at PMA_DisplayResults class, so I won't be able to go into specifics about your tests, but I will try to answer your questions, and point you in a direction.
Accessing or setting private variables in a class/method is not possible during a unit test. The idea of unit tests is to test the functionality of a class method or global function by testing the output of it, or catching errors. You expect a certain behaviour of the method/function depending on the value of the input parameters (or environmental states, like global variables, database content, or config settings). So basically you think of all different situations that can affect the behaviour of the method/function, define what kind of result this would give and write a test that sets up the situation and test (assert) the output of the function/method.
When writing unit tests, you should keep in mind that you are only testing the behaviour of that function/method. Any functions/methods used by a function/method should be tested seperately. By which I mean that you must assume when testing a function/method that the functions/methods that are used in that method, work correctly. To make things easier for you, you can define stubs/mocks [0] that replace the methods/functions used in a function/method you are testing. This way you don't have to set up a complete environment, but can concentrate on what the function/method does.
As an example
If you have a class that gets values from a database :
class DbValues { private $_values;
__construct() { $this->_values = array(); }
public function getValuesFromDb() { // functionality making a connection to a database, executing a query and setting the resulting values to $_values. }
public function getValues() { return $this->_values; }
public function count() { return count($this->getValues()); } }
And you want to test the behaviour of the count() method. The only way to populate the _values variable in this example would be by setting up a database with different sets of values, for each case you want to test and call the getValuesFromDb() method, OR, you can define a stub that replaces the getValues() method and let it return an array with the necessary amount of values (depending on what you want to test). This way you avoid having to set up a complicated testing environment, when testing a single class method. (Note : when testing the getValuesFromDb() method you will probably have to set up a database, but that's because that method is all about connecting to a database and getting data from it, but all other methods in this class can assume that the getValuesFromDb works, so there is no need to replicate the complicated test environment every time)
I suggest you read up a bit on testing class methods and the use of stubs/mocks. I hope my example didn't confuse you too much.
[0] http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs
Thank you very much for spending your time for clarify this with valuable and enough information. I completely agree with you, on writing unit tests independent/separate from another layer/function. Mock objects/stubs are helpful in that case.
At the moment there are around 25 private fields in PMA_DisplayResults class. What I am thinking of implement getter setter methods for all those and use getters and setters where needed. In that way I will be able to set those private fields even from the tests. What do you think on this ?
Regards !
Hi Chanaka,
When writing test cases we might have to test protected/private functions as well. The method used in PMA is by using php Refection class. They used setAccessible method to make them public for test class. There is a method in reflection class called getProperties which can used for access protected and private attributes. Refer this [1] for more details. But I am not sure is it a good approach when testing.
[1] - http://php.net/manual/en/reflectionproperty.setaccessible.php
Hi Yasitha,
Thanks for your information. I have already referred some tests done by you, accessing to private functions. I'll use the same way for testing private methods.
Regards !