For example, if I have a method that execute simple logic and take an int parameter in input, do I have to unit test cases when input is :
a good int (like 1)
a bad int (like 822873873824676372732367232637233)
a descent float
a bad float
a bool
a string
no parameter
Well I think I already know the answer, but where is the limit?
Also, when the method have A and B parameters, do I have to test every cases that could happens by doing these methods? :
testGoodAWithoutB
testGoodBWithoutA
testGoodAWithGoodB
testBadAWithoutB
testGoodAWithBadB
...
The answer to your question is: no, of course not.
It makes no sense to test every possible value. If you are working with unit tests I guess that you are trying to ceap your code as clean as possible. For this your function should follow the single responsibility principle.
If your function just hase one functionality it makes it easy just to test that.
It depends also what your function can expect. When you have a function add(a, b) it depends on the context inside your programms. When the error handling is done before the function call and you are sure that you will always get valid values there is no need to test this, because your function is not responsible for that. If the same function is for example a public method the function has to check the input values. In that case you should also test that.
You need to keep in mind that your tests has to be readeable for humans. If you are testing everything which could happen the next 100 years the tests will be not so easy to understand.
Your tests should also be something like a documentation for other programmers. So just test your function like your function should be called.
Related
My apologies if the title isn't clear, but I find this difficult to describe. Basically, I have a function that looks for an instance of a class (the school kind) given a class ID number and a date. The function can also create a new class instance if desired.
function get_class_instance($class_id, $date, $create)
Inside the function is a database select on the class_instances table using the class_id and date as arguments. If a matching class_instance is found, its ID is returned. If none is found, there's a conditional for the create argument. If it's true, a new class_instance is created using a database insert and its ID is returned. If false, nothing is changed in the database and false is returned.
I'm still a beginner with PHP and coding generally, so I'm thinking there is probably a better way. The issue is that when calling the function, it might not be clear to someone why there is a boolean being passed.
$original_cinstance_id = get_class_instance($original_class_id, $original_date, 1);
Passing boolean flags to functions to make them do two different things instead of just one is considered a Code Smell in Robert Martin's Clean Code book. The suggested better option would be to have two functions get_whatever and create_whatever.
While a Code Smell depends on context, I think the boolean flag smell does apply in this case, because creating something is different from merely reading it. The former is a Command and the latter is a Query. So they should be separated. One changes state, the other doesn't. It makes for better semantics and separation of concerns to split them. Also, it will reduce the Cyclomatic Complexity of the function by one branch, so you will need one unit-test less to cover it.
Quoting https://martinfowler.com/bliki/FlagArgument.html
Boolean arguments loudly declare that the function does more than one thing. They are confusing and should be eliminated.
Quoting http://www.informit.com/articles/article.aspx?p=1392524
My reasoning here is that the separate methods communicate more clearly what my intention is when I make the call. Instead of having to remember the meaning of the flag variable when I see book(martin, false) I can easily read regularBook(martin).
Additional discussion and reading material:
https://softwareengineering.stackexchange.com/questions/147977/is-it-wrong-to-use-a-boolean-parameter-to-determine-behavior
https://medium.com/#amlcurran/clean-code-the-curse-of-a-boolean-parameter-c237a830b7a3
https://8thlight.com/blog/dariusz-pasciak/2015/05/28/alternatives-to-boolean-parameters.html
You can use a default value for create, so if you pass anything to it, it acts as a normal "get" operation for the database. Like this:
function get_class_instance($class_id, $date, $create = false);
You can query your ID's like this:
$class_id = get_class_instance(1, "18-10-2017");
You can then pass "true" to it whenever you need to create it on the database:
$class_id = get_class_instance(1, "18-10-2017", true);
Instead of passing a number value, you can pass a real boolean value like this:
$original_cinstance_id = get_class_instance($original_class_id, $original_date, true);
Also in the declaration of your function, you can specify a default value to avoid to pass the boolean each time:
function get_class_instance($class_id, $date, $create = false)
one option is to create an enumerator like so:
abstract class create_options {
const no_action = 0;
const create = 1;
}
so now your function call would look like this:
$original_cinstance_id = get_class_instance($original_class_id, $original_date, create_options::no_action);
in practice as long as your code is well commented then this isn't a major issue with boolean flags, but if you had a dozen possible options with different results then this could be useful.
As others have mentioned, in many languages you can also make an argument optional, and have a default behavior unless the caller specifically defines that argument.
Is there any harm to having functions one lined instead of multilined? For example, I wrote a class file for a PDO database connection. All the functions I wrote for it, are one lined. I haven't run into any errors yet, but can they crop up if there is lag or something?
Here are some of the functions.
public function getObject($query, $object) {
return $this->db->prepare("$query")->execute()->fetch(PDO::FETCH_OBJ)->$object;
}
public function getArray($query) {
return $this->db->prepare("$query")->execute()->fetchAll(PDO::FETCH_NUM);
}
public function insertArray($query, $array) {
return $this->db->prepare("$query")->execute($array);
}
Will this eventually run into problems? Or do they get called one section at a time, as if they were on their own line?
Thanks.
Using chained methods in one single line like this
return $this->db->prepare("$query")->execute()->fetch(PDO::FETCH_OBJ)->$object;
is what Robert Martin calls "Train Wrecks" in Clean Code (pg 98/99). It's hard to read and "generally considered sloppy" and should be avoided for the more readable
$statement = $this->db->prepare("$query");
$statement->execute();
$result = $statement->fetch(PDO::FETCH_OBJ);
return $result->$object;
Please note that I corrected the code in the snippet above, as your one-liner will not work, because execute returns a boolean, so you cannot call fetch on it:
bool PDOStatement::execute ([ array $input_parameters ] )
In other words, you cannot write this as a one-line statement anyway.
Also note that Method Chaining is very often a violation of the Law of Demeter, which states that
a method M of an object O may only invoke the methods of the following kinds of objects:
O itself
M's parameters
any objects created/instantiated within M
O's direct component objects
a global variable, accessible by O, in the scope of M
Not following LoD usually leads to Mockfests in your UnitTests and makes your application tightly coupled to much more classes than necessary, which in turn impairs reusability and increases the time required for changes (among other things).
Imperative code will always get called in the expected order. There is nothing to worry about, except maybe if the code is readable or not. In case where the line is very very long, you might want to wrap it to multiple lines, but the examples you show look OK to me.
If the connection to the database fails for some reason it could cause a FATAL_ERROR because one of the objects will return false.
When i write down a function is a good practice to validate all the parameters of the function like this:
<?php
/**
* foo - Test function
*
* #param int $paramA
* #param str $paramB
* #param array $paramC
*
* #return something
*/
function foo($paramA, $paramB, $paramC) {
// verify all parameters
if(!is_int($paramA)) {
return 0; // or error msg
}
if(!is_string($paramB)) {
return 1; // or error msg
}
if(!is_array($paramC)) {
return 2; // or error msg
}
// some code in function scope that uses parameters
// and saves the results in $result
return $result;
}
or should i rely on the user that will use the function and assume that he knows what he is doing and forget about parameter validation?
Personally i prefer to validate all the parameter of the function and return error codes for consistency of the code and make my life easier afterwords.
Thank you in advance.
I think the answer is: it depends
It depends on who you are writing your code for. If you're looking for the most generalized answer, then yes, you should.
If your script will only ever be used by you and you know in your heart of hearts that you will always use it correctly, then you will (probably) be safe if you don't.
If your script is part of an API that will be distributed to many, many people, then you most definitely want to add error checking and provide good fall back error messages for people.
If you are part of a small team that will all be using the same code, I would also suggest that validating your arguments according to your particular context would be a good idea.
If it is an internal function that only you will be using, it is probably okay to not validate every single parameter like that. If it is a function that has parameters that depend on user input (for example, you get information through $_GET, and then pass that to a function), then it needs to be validated.
Never rely on a user or anyone else besides yourself to know what they are doing. Sometimes it can be helpful to validate things like this if you are writing code that you can re-use later (like if you were writing your own framework to use across all of your PHP projects). But if it is just one application-specific function that only you can call with parameters that only you define, I wouldn't worry about it.
Why validate your parameters:
Sometimes we really need a certain datatype for an operation. If you give me a string that is not representative of an integer and you use that as a search for a primary key in a database (usually an int), then you will have trouble.
It makes fixing your code easier. When you are checking parameters, you can throw individual exceptions and give messages that are very descriptive. This makes it easier to fix your code when something breaks, because you know exactly what went wrong.
Some tips on type checking:
In case you didn't know, is_int is pretty faulty. I think a valid check to see if it is an int is is_numeric($int) && $int==(int)$int.
You can specify types for objects and arrays, like so: function foo($paramA, $paramB, array $paramC).
Really depends on the type-strictness of what you're doing with those parameters.
Since PHP is weakly typed, you can get away with a lot by casting or just letting the implicit type conversion/coercion do it's thing.
And if you're just going to throw a bunch of guard conditions at the head of every function only to return errors, that's really not much different than PHP triggering errors of its own.
I beg to differ. I recently stumbled upon an article about a similar issue (null checks), but it seems to apply for type checking in php as well. I agree with the author.
Write code in a way that makes type checking redundant.
explicitly validate user input and cast the values to the required types as soon as possible.
In some exceptional cases, you can and should use exceptions instead of returning some obscure error numbers.
It is a very good practice to validate function arguments. I suspect you ask this question because on the other hand it makes your functions look longer and uglier. However with args module from NSPL, it is very easy to do. The function from your example will be:
function foo($paramA, $paramB, array $paramC)
{
expects(int, $paramA);
expects(string, $paramB);
// do something
}
// or type check several arguments
function sum($x, $y)
{
expectsAll(numeric, [$x, $y]);
return $x + $y;
}
More examples here.
I'm wondering what you think the best practice is here-- does it buy you very much to type-check parameters in PHP? I.e have you actually seen noticeably fewer bugs on projects where you've implemented parameter type-checking vs. those that don't? I'm thinking about stuff like this:
public function __construct($screenName, $createdAt) {
if (!is_string($screenName) || !is_string($createdAt) {
return FALSE;
}
}
Normally within a PHP application that makes use of the skalar variable "types" is bound to actually string input (HTTP request). PHP made this easier so to convert string input to numbers so you can use it for calculation and such.
However checking scalar values for is_string as proposed in your example does not make much sense. Because nearly any type of variable in the scalar family is a string or at least can be used as a string. So as for your class example, the question would be, does it actually make sense to check the variable type or not?
For the code you proposed it does not make any sense because you exit the constructor with a return false;. This will end the constructor to run and return a not-properly-initialized object.
Instead you should throw an exception, e.g. an InvalidArgumentException if a constructors argument does not provide the expected / needed type of value.
Leaving this aside and taking for granted that your object constructor needs to differ between a string and an integer or bool or any other of the scalar types, then you should do the checks.
If you don't rely on the exact scalar types, you can cast to string instead.
Just ensure that the data hidden inside the object is always perfectly all-right and it's not possible that wrong data can slip into private members.
It depends. I'll generally use the type-hinting that is built into PHP for higher-level objects ((stdClass $obj, array $arr, MyClass $mine)), but when it comes to lower level values -- especially numbers and strings, it becomes a little less beneficial.
For example, if you had the string '12345', that becomes a little difficult to differentiate between that and the number 12345.
For everything else, the accidental casting of array to a string will be obvious. Class instances which are cast to strings, if they don't have a __toString, will make PHP yell. So your only real issue is classes which have a __toString method and, well, that really limits the number of times where it can come up. I really wonder if it is worth that level of overhead.
Checking function arguments is a very good practice. I suspect people often don't do that because their functions grow bigger and the code becomes uglier and less readable. Now with PHP 7 you can type-hint scalar types but there is still no solution for cases when you want your parameter to be one of two types: array or instance of \Traversable (which both can be traversed with foreach).
In this case, I recommend having a look at the args module from NSPL. The __constructor from your example will have the following look:
public function __construct($screenName, $createdAt)
{
expectsAll(string, [$screenName, $createdAt]);
}
// or require a non-empty array, string or instance of \ArrayAccess
function first($sequence)
{
expects([nonEmpty, arrayAccess, string], $sequence);
return $sequence[0];
}
More examples here.
Better documentation is more important when you're the only one interacting with the methods. Standard method definition commenting gives you well documented methods that can easily be compiled into an API that is then used in many IDEs.
When you're exposing your libraries or your inputs to other people, though, it is nice to do type checking and throw errors if your code won't work with their input. Type checking on user input protects you from errors and hacking attempts, and as a library letting other developers know that the input they provided is not what you're expecting is sometimes nice.
I am not really clear about declaring functions in php, so I will give this a try.
getselection();
function getselection($selection,$price)
{
global $getprice;
switch($selection)
{
case1: case 1:
echo "You chose lemondew <br />";
$price=$getprice['lemondew'].'<br>';
echo "The price:".$price;
break;
Please let me know if I am doing this wrong, I want to do this the correct way; in addition, php.net has examples but they are kind of complex for a newb, I guess when I become proficient I will start using their documentation, thank you for not flaming.
Please provide links that might also help me clear this up?
Your example seems valid enough to me.
foo('bar');
function foo($myVar)
{
echo $myVar
}
// Output: bar
See this link for more info on user-defined functions.
You got off to a reasonable start. Now all you need to do is remove the redundant case 1:, close your switch statement with a } and then close your function with another }. I assume the global array $getprice is defined in your code but not shown in the question.
it's good practice to declare functions before calling them. It'll prevent infrequent misbehavior from your code.
The sample is basically a valid function definition (meaning it runs, except for what Asaph mentions about closing braces), but doesn't follow best practices.
Naming conventions: When a name consists of two or more words, use camelCase or underscores_to_delineate_words. Which one you use isn't important, so long as you're consistent. See also Alex's question about PHP naming conventions.
Picking a good name: a "get" prefix denotes a "getter" or "accessor"; any method or function of the form "getThing" should return a thing and have no affects visible outside the function or object. The sample function might be better called "printSelection" or "printItem", since it prints the name and price of the item that was selected.
Globals: Generally speaking, globals cause problems. One alternative is to use classes or objects: make the variable a static member of a class or an instance member of an object. Another alternative is to pass the data as an additional parameter to the function, though a function with too many parameters isn't very readable.
Switches are very useful, but not always the best choice. In the sample, $selection could easily hold the name of an item rather than a number. This points to one alternative to using switches: use an index into an array (which, incidentally, is how it's done in Python). If the cases have the same code but vary in values used, arrays are the way to go. If you're using objects, then polymorphism is the way to go--but that's a topic unto itself.
The $price parameter appears to serve no purpose. If you want your function to return the price, use a return statement.
When you called the function, you neglected to pass any arguments. This will result in warnings and notices, but will run.