How important is checking for bad parameters when unit testing? - javascript

Let's say I've got a method that takes some arguments and stores them as instance variables. If one of them is null, some code later on is going to crash. Would you modify the method to throw an exception if null arguments are provided and add unit tests to check that or not? If I do, it's slightly more complicated since javascript has many bad values (null, undefined, NaN, etc.) and since it has dynamic typing, I can't even check if the right kind of object was passed in.

I think it really depends on what sort of API you're unit testing. If this is a component designed and built for internal use only, and you know usage will be under certain constraints, it can be overkill to unit test for bad parameters. On the other hand, if you're talking about something for distribution externally, or which is used in a wide variety of situations, some of which are hard to predict, yes, checking for bad parameters is appropriate. It all depends on usage.

I think you really have 2 different questions here.
The first is what is the best practice for parameter input validation and the second is should your unit test handle test for these situations.
I would recommend that you either throw an Argument Exception for the parameter that was not supplied correctly to your function or some other variable/message that informs the calling function/user of the situation. Normally, you do not want to throw exceptions and should try to prevent the functions from even being called when you know they will fail.
For your unit test, you should definitely include NULL value tests to make sure a graceful result occurs.

JavaScript has instanceof and typeof that can help you check what kind of objects are being passed to your functions:
'undefined' == typeof noVariable; // true
var noVariable = null;
'undefined' == typeof noVariable; // false
typeof noVariable; // 'object'
noVariable === null; // true
var myArray = [];
typeof myArray; // 'object'
myArray instanceof Object; // true
myArray instanceof Array; // true
var myObject = {};
typeof myObject; // 'object'
myObject instanceof Object; // true
myObject instanceof Array; // false
You can use these to set some default "bad" values for your instance variables:
function myFunction(foo,bar) {
foo = foo instanceof Array ? foo : []; // If 'foo' is not an array, make it an empty one
bar = bar instanceof Number ? bar : 0;
// This loop should always exit without error, although it may never do a single iteration
for (var i=0; i<foo.length; i++) {
console.log(foo[i]);
}
// Should never fail
bar++;
}
The or operator is also very useful:
function myFunction(blat) {
var blat = blat||null; // If 'blat' is 0, '', undefined, NaN, or null, force it to be null
// You can be sure that 'blat' will be at least *some* kind of object inside this block
if (null!==blat) {
}
}

Also, don't forget that with JavaScript you can pass in fewer than or more than the expected number of parameters. You can check that too, if you like.

For creating robust and secure code, checking the edge cases is definitely important task. Positive and negative testing is always good for the quality. The lack of negative tests might bite you in the long run.
So I'd say it is better play it safe - do both. It's a bit more work, but if you can afford the time, then it'll be worth it. Taking the developer hat off and putting on the cracker hat can be very interesting sometimes.

Related

How to check if a function does anything? [duplicate]

Let's have a function call
function doSomethingAndInvokeCallback(callback){
// do something
callback();
}
I can check if given argument is function if(typeof callback == 'function')
How can I discover, if given callback function is function and isn't empty?
like
doSomethingAndInvokeCallback(function(){
//nothing here
})
There is no totally reliable way to know if a function is empty because there are multiple kinds of functions in JS, some implemented with JS and some implemented with native code and you can't know for sure whether the function passed in does anything or not. If you want to limit the passed in function to only very simple JS functions, you could use the mechanisms outlined by other answers here (examining the source of the function). But, I would not recommend doing that in anything but a tightly controlled situation because there are lots of legal javascript ways to break that.
I would suggest that you should change the contract of your function arguments and have the caller pass null or not pass anything (which will make the argument undefined) rather than an empty function. Then, it will be very clear whether they intend to have a function called or not. If they then pass an empty function instead of null or undefined, they are getting the behavior that the interface of the function specifies. The caller can choose the desired behavior and you can implement your function in a more failsafe manner.
Also, one of your main suppositions in your question is not quite right. You cannot safely use typeof x == "function" to determine if something is a function as that will not work reliably in some older versions of IE for some types of functions. If you want to learn how to detect if something is a function at all, you can learn from jQuery here (even if you're not using it). jQuery has a function it uses internally all the time called jQuery.isFunction() that returns a bool. It uses that mostly for testing arguments to see if a function was passed.
Internally, it calls:
Object.prototype.toString.call(o)
and then examines the result. If the result has "Function" in it, then test test parameter is a function.
So, using the same technique used in jQuery, you could build your own simple little isFunction routine like this:
function isFunction(test) {
return(Object.prototype.toString.call(test).indexOf("Function") > -1);
}
Of course, if you have jQuery available, you could just use it's own version:
jQuery.isFunction(o)
When there are questions with potential cross browser compatibility issues, I find it instructional to look at how one of the big libraries solves the issue, even if you aren't going to be using that library. You can be sure that the libraries have been vetted against many browsers so a technique they are using is safe. You sometimes have to unwrap all their own internal routines they may use to figure out what they're really doing (which was the case for this function), but you can save yourself a lot of legwork.
You can see a working test bed for this here: http://jsfiddle.net/jfriend00/PKcsM/
In modern browsers typeof fn === "function", but in older versions of IE, some functions give a typeof === "object" which is probably why jQuery uses this other method which does work in those older versions of IE.
It seems that you can define a function to retrieve the body of a function(1). I wrote a small (non-definitive) test of this:
http://jsfiddle.net/6qn5P/
Function.prototype.getBody =
function() {
// Get content between first { and last }
var m = this.toString().match(/\{([\s\S]*)\}/m)[1];
// Strip comments
return m.replace(/^\s*\/\/.*$/mg,'');
};
function foo() {
var a = 1, b = "bar";
alert(b + a);
return null;
}
console.log(foo.getBody());
console.log(foo.getBody().length);
One possibility is matching the .toString result against a regexp to get the function body, and then trim to check whether it has become an empty string:
var f = function foo() {
};
/^function [^(]*\(\)[ ]*{(.*)}$/.exec(
f.toString().replace(/\n/g, "")
)[1].trim() === ""; // true
That ugly regexp does take care of spaces aroung named functions as well as extraneous spaces before the name and the opening brace. Spaces like in foo () do seem to be removed, so there is no reason to check for those.
You might be able to get this from .toString():
var blank = function(){};
var f = function(){};
var f2 = function() { return 1; };
f.toString() == blank.toString(); // true
f2.toString() == blank.toString(); // false
but this is really prone to error:
var blank = function(){};
var f = function(){ }; // extra space!
f.toString() == blank.toString(); // false
You could munge the strings a bit to try to overcome this, but I suspect this is very browser-dependent. I wouldn't actually try to do this in a production environment if I were you. Even if you normalize the whitespace, it still won't catch other no-op lines, including comments, useless var statements, etc. To actually address these issues, you'd probably need a whole tokenizer system (or a crazy regex).
You can't do it for a host function, but for others, you can fairly reliably do
function isEmpty(f) {
return typeof f === "function" &&
/^function[^{]*[{]\s*[}]\s*$/.test(
Function.prototype.toString.call(f));
}
This isn't efficient, but major interpreters implement toString for functions in such a way that it works, though it will not work on some interpreters for some empty-ish functions
function () { /* nothing here */ }
function () { ; }
function () { return; }
In some implementation you can just do a toString() on the function and get it's content. Though it contains comments etcetera.
var foo = function(){ /* Comment */ };
alert(foo.toString());

Best way to check undefined element in an array

I have an array linking integers to objects:
var array = [];
array[3] = new Something();
array[42] = new OtherSomething();
array[84] = new SomethingAgain();
I want to check if an field exists in an array, and then use it if it does.
var field = array[row];
If the array doesn't contain any field with index row, then field will be set to undefined.
My question is: what is the best way to check its existence between:
if (field !== undefined) { /* Do stuff with field */ }
And:
if (field) { /* Do stuff with field */ }
The second solution is shorter, so it could be quicker to execute, because JavaScript is an interpreted scripting language. But in another hand, it might check for boolean value of field, or something like that...
What is your point on this ?
The array what you created is called a sparse array. You can read more about it in this answer.
The check
if (field !== undefined)
might not help if the actual value stored in the array itself is undefined. And this check
if (field)
will evaluate to be truthy if field is any one of the Truthy values. You can read more about the Truthiness and Falsiness of different values in this answer.
So, if you want to know if the array has a particular index, then you can use Object.prototype.hasOwnProperty, like this
var array = [];
array[1] = undefined;
console.log(array[0]);
// undefined
console.log(array[1]);
// undefined
console.log(array.hasOwnProperty(0));
// false
console.log(array.hasOwnProperty(1));
// true
Here the element at 1 is defined to be undefined, but since 0 is not defined at all, by default, JavaScript returns undefined.
The hasOwnProperty call checks if the current object really has the index 0 and 1.
"Best" is a fairly subjective term, so let's throw some objective criteria at it:
Which is faster?
In a way that you'll notice in the real world, neither. But if you really want to know, measure your specific code on the engines you want to support.
Which is easier to read?
This is probably subjective as well. The second form is extremely common in JavaScript, FWIW.
Which is less typing?
The second form is obviously a lot shorter than the first.
Which is more reliable?
Given your use case, they're equally reliable, because you're either not storing an entry in the array at all, or storing a non-null object reference.
In similar but different use cases, you might need to be wary of the difference: The first form will only be true for an entry that exists and doesn't have the value undefined in it. The second form will be true for anything that isn't falsey. There are several falsey values: null, undefined, 0, "", NaN, and of course, false. So you wouldn't use the second form to decide whether there was a number at a position in the array, since 0 is a number but if (0) won't go into the body of the if.
Speaking of ambiguity, note that comment about "...true for an entry that exists and doesn't have the value undefined in it..." Neither of the examples you gave differentiates between an entry that doesn't exist and an entry that exists with the value undefined. If you need to differentiate those at some point (again, not for the use case you mentioned), you'd use hasOwnProperty on the array: if (array.hasOwnProperty(row))
The second solution is shorter, so it could be quicker to execute, because JavaScript is an interpreted scripting language
This is a mistaken assumption. Most modern JavaScript engines are just-in-time optimizing compilers. V8 (the engine in Chrome), for instance, is a two-stage optimizing compiler: On the first pass, it turns your JavaScript into machine code quickly, and then if it identifies hotspots (bits of code that run a lot), it goes back and does more aggressive optimization there.
I'll give you this example. Hope it helps you feel clearer.
var arr = [];
arr[0] = 0;
arr[1] = undefined;
arr[2] = null;
arr[3] = NaN;
arr[4] = '';
arr[5] = false;
arr[11] = 1;
arr[12] = [];
arr[13] = {};
arr[14] = 'hello';
arr[15] = true;
if(arr[0]) //false but exists
if(arr[1]) //false but exists
if(arr[2]) //false but exists
if(arr[3]) //false but exists
if(arr[4]) //false but exists
if(arr[5]) //false but exists
if(arr[6]) //false and not exist
if(arr[7]) //false and not exist
if(arr[8]) //false and not exist
if(arr[9]) //false and not exist
if(arr[10]) //false and not exist
if(arr[11]) //true and exists
if(arr[12]) //true and exists
if(arr[13]) //true and exists
if(arr[14]) //true and exists
if(arr[15]) //true and exists
In general, I recommend you to use the second solution for checking existence since it's shorter and easier to read. However, it still strongly depends on your case. Make sure that your choice is not going to fail in any unexpected situations.

Javascript Coding Practices: Empty Values in Objects

Just read this highly-related question, and then reflected on what I was using in my own code base for a project at work.
I wrote a simple function to demonstrate this question (using Google Apps Script, thus the calls to Logger.log()):
function emptyValueTest() {
var object = {
prop1: "real_data",
prop2: "",
prop3: undefined,
prop4: null
}
// What I have used in my code personally. All evaluate to TRUE
if (object.prop2 === "") Logger.log("prop2 was empty");
if (typeof object.prop3 === "undefined") Logger.log("prop3 was undefined");
if (object.prop4 === null) Logger.log("prop4 was null");
// The other solution I've seen. All evaluate to FALSE
if (object.prop2) Logger.log("prop2 was empty");
if (object.prop3) Logger.log("prop3 was undefined");
if (object.prop4) Logger.log("prop4 was null");
}
I've been building a system for the past few months with thousands of lines of code, and I often find myself back-tracking when I see a particular value, to remember what it's previous state was before a particular conditional expression.
Since I'm the one writing the code it isn't too difficult for me to figure it out, because I know the structure of the data, the values that are supposed to be there, etc.
However, this system will be taken over by another developer after I graduate from my university, so I wonder what the best practice is for representing that a property has no data.
For example, my use case is that I have event Objects which are initialized with empty data and, during the lifetime of a semester, are eventually filled with real data. Personally I use undefined because it makes more sense to me to read if (typeof data === "undefined"), having a similar semantic meaning to "if this data is undefined" (i.e. no value yet).
But I wonder, in industry, in libraries, and in personal projects, what are commonly-used methods to make code more readable, understandable? Though the length of the first three conditionals is longer than the latter three, I find the latter three to be ambiguous.
For example, prop2 could have a non-empty string like "data", or the value true, which would cause the latter conditional if (object.prop2) to evaluate to true in both cases, because everything in JavaScript is truthy except the following:
null
undefined
NaN
empty string ("")
0
false
And it is entirely possible that data could have "", 0, and false as valid values, whereas null, undefined and (especially) NaN are probably not typical values for real data.
Obviously I we know the structure of the data then we might impose more strict checks to disambiguate non-empty strings from true. But in a project with thousands of lines of code it seems to me that this gets out of hand fast, especially if the structure of the data changes over time.
So my question: Is there a preferred method of representing empty values in Javascript? And is there a particular reason for the preference (performance, readability, scalability, etc.)?
Javascript is especially insidious in the NaN constant:
alert(NaN==NaN?"isNaN":"isNotNaN"); // isNotNaN !
The most common way to represent empty object is the null constant. However, you can run into troubles using it:
var coords = null;
if(coords===null) alert("empty object");
if(coords.x==0 && coords.y==0) alert("[0,0]");
// Uncaught TypeError: Cannot read property 'x' of null
There is a design pattern called Null object: to create an object representing null value with correct properties:
var nullcoords = {x:-1,y:-1}; // null object
var coords = nullcoords;
if(coords===nullcoords) alert("empty coords");
if(coords.x==0 && coords.y==0) alert("[0,0]");
// no TypeError
As RobG points in the comment, you can afford this attitude iff
the nullobject default properties are not valid values
the default values don't spoil you operations
However, null is not a good idea for coords properties since it is not a numeric type and can mess some arithmetic operations (not in JS, though). The below code is more appropriate (and more sophisticated) solution with custom null object handler:
function nullCoordsHandler(obj) {
// any error handling you want
alert("setting default values...");
obj.x = obj.y = 0;
}
function coords() {
var _x, _y;
var defined = false;
Object.defineProperty(this,"x",{
enumerable: true,
get:function() { if(!defined) nullCoordsHandler(this); return _x; },
set:function(value) { defined = true; _x = value; }
});
Object.defineProperty(this,"y",{
enumerable: true,
get:function() { if(!defined) nullCoordsHandler(this); return _y; },
set:function(value) { defined = true; _y = value; }
});
};
var c = new coords();
if(c.x==0 && c.y==0) alert("[0,0]");
// nullCoordsHandler was called to handle the null object situation

JavaScript object detection: dot syntax versus 'in' keyword

I have seen two ways of detecting whether a UA implements a specific JS property: if(object.property) and if('property' in object).
I would like to hear opinions on which is better, and most importantly, why. Is one unequivocally better than the other? Are there more than just these two ways to do object property detection? Please cover browser support, pitfalls, execution speed, and such like, rather than aesthetics.
Edit: Readers are encouraged to run the tests at jsperf.com/object-detection
if(object.property)
will fail in cases it is not set (which is what you want), and in cases it has been set to some falsey value, e.g. undefined, null, 0 etc (which is not what you want).
var object = {property: 0};
if(object.isNotSet) { ... } // will not run
if(object.property) { ... } // will not run
if('property' in object)
is slightly better, since it will actually return whether the object really has the property, not just by looking at its value.
var object = {property: 0};
if('property' in object) { ... } // will run
if('toString' in object) { ... } // will also run; from prototype
if(object.hasOwnProperty('property'))
is even better, since it will allow you to distinguish between instance properties and prototype properties.
var object = {property: 0};
if(object.hasOwnProperty('property')) { ... } // will run
if(object.hasOwnProperty('toString')) { ... } // will not run
I would say performance is not that big of an issue here, unless you're checking thousands of time a second but in that case you should consider another code structure. All of these functions/syntaxes are supported by recent browsers, hasOwnProperty has been around for a long time, too.
Edit: You can also make a general function to check for existence of a property by passing anything (even things that are not objects) as an object like this:
function has(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
Now this works:
has(window, 'setTimeout'); // true
even if window.hasOwnProperty === undefined (which is the case in IE version 8 or lower).
It really depends what you want to achieve. Are you talking about host objects (such as window and DOM nodes)? If so, the safest check is typeof, which works for all host objects I know of:
if (typeof object.property != "undefined") { ... }
Notes:
Avoid object.hasOwnProperty() for host objects, because host objects are not obliged to inherit from Object.prototype and therefore may not have a hasOwnProperty() method (and indeed in IE < 9, they generally do not).
A simple Boolean coercion (e.g. if (object.property) { ... }) is a poor test of the existence of a property, since it will give false negatives for falsy values. For example, for an empty textarea, if (textarea.selectionStart) { ... } will not execute the block even though the property exists. Also, some host object properties throw an error in older versions of IE when attempting to coerce to a Boolean (e.g. var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }).
The in operator is a better test of the existence of a property, but there are once again no guarantees about support for it in host objects.
I recommend against considering performance for this kind of task. Choose the safest option for your project and only optimize later. There will almost certainly be much better candidates for optimization than property existence checks.
For more background on this, I recommend this excellent article by Peter Michaux.
Definitely if ('property' in object) is the right way to go. That actually tests if the property is in the object (or in its prototype chain, more on that below).
if (object.property) on the other hand, will coerce 'property' into a truth/flase value. If the property is unset, it will return "undefined", which will be coerced into false, and appear to work. But this will also fail for a number of other set values of properties. javascript is notoriously inconsistent in what it treats as truthy and falsy.
Finally, like I said above, 'property' in 'object' will return true if it's in anywhere in the prototype chain. If you want to test that's on the object itself, and not somewhere higher up in the chain, you use the hasOwnProperty method like so:
if (object.hasOwnProperty('property')) ...
The first one would fail if "property" is false of 0. To make sure that there actually exist a property you need to check that object.property !== undefined, or use the in-keyword.
[Edit]
There is also the hasOwnProperty-function, but I've never really used that one so I can't say much about it. Though I think it won't return true if the property is set in a prototype, which sometimes you want, other times you don't want.
This allows you to use window.hasOwnProperty as either referring to itself or something else, regardless of your scripting host.
// No enclosing functions here
if (!('hasOwnProperty' in this))
function hasOwnProperty(obj, prop) {
var method = Object.prototype.hasOwnProperty;
if (prop === undefined)
return method.call(this, obj);
return method.call(obj, prop);
}
//Example of use
var global = global || this; //environment-agnostic way to get the global object
var x = 'blah';
WScript.Echo(global.hasOwnProperty('x') ? 'true' : 'false'); //true
//Use as non-object method
var y = { z: false };
WScript.Echo(hasOwnProperty(y, 'z') ? 'true' : 'false'); //true
WScript.Echo(hasOwnProperty(y, 'w') ? 'true' : 'false'); //false
// true ಠ_ಠ
WScript.Echo(hasOwnProperty(global, 'hasOwnProperty') ? 'true' : 'false');

Handling the distinction between undefined- and null-parameters in JavaScript

I know very well that null and undefined are distinct in JavaScript. However, I can't seem to decide whether or not use that fact when my own functions are passed one of those as its argument.
Or, expressed in a different way, should myFoo(undefined) return the same thing as myFoo(null)?
Or, in yet another case, since myBar(1, 2, 3) is (almost) the same thing as myBar(1, 2, 3, undefined, undefined), should myBar(1, 2, 3, null, null) return the same thing as myBar(1, 2, 3)?
I feel that there's potential for confusion in both cases and that a library should probably follow a convention when handling null/undefined.
I'm not really asking for personal opinions (so please express those as comments rather than answers). I'm asking if anyone knows if there is a best practice that one should stick to when it comes to handling this distinction. References to external sources are very welcome!
I'd say that while, most of the time, there is little value in distinguishing between the two, the cases where there is value tend to be quite interesting.
Take, for example, a function which can be given a callback. undefined might indicate that some default callback should be used (as if the parameter weren't specified), but null could indicate that no callback should be made at all:
function asyncWorker(data, callback, timeout) {
if (typeof callback === "undefined") {
callback = function() { $("#log").append("<p>Done!</p>"); };
}
// ...
if (callback) callback();
}
asyncWorker([1, 2, 3]); // default callback, no timeout
asyncWorker([4, 5, 6], null); // no callback, no timeout
asyncWorker([7, 8, 9], undefined, 10000); // default callback, 10s timeout
Of course, false or 0 could be used instead of null here, but that might not be the case in a more complex example. And whether your code benefits from the additional parameter complexity is entirely up to you. :-)
Best practice for handling arguments
define the expected arguments, what they will be used for, and the types of these
decide how they are accessed, either via the formal arguments, or through the arguments collection
define whether values outside the expected range should result in default values
verify that the arguments are within range before processing
for boolean values, decide whether they must be true booleans, or only truthy/falsy
Step 2, 3 and 4 is of most importance to you in this case
How to access the arguments
This is something you will need to select based on what the method does, and your strategy for handling a variable amount of arguments.
Take this for example
function foo() {
var args = arguments.length == 1 ?
[document.body].concat([arguments[0]]) :
Array.prototype.slice.call(arguments);
args[0].style.backgroundColor = args[1];
}
foo(document.body, "red");
foo("blue");​
True boolean or truthy/falsy
How to test for values depends largely on how your code is set up
function foo(elem, color) {
if (!color) { // the correct test here should be 'typeof color == "undefined"'
color = "green";
}
elem.style.backgroundColor = color;
}
foo(document.body, "red"); //set the background color to red
foo(document.body); //set the background color to the default green
foo(document.body, "");​ //remove the background color !This will fail!
The last statement will wrongly use the default value instead of the provided, even though the provided is within the expected range.
When it comes to handling undefined values remember that there is no difference in foo(undefined); and foo(); except that the length of the arguments collection will be different. How this is handled (and if it needs to be) is dependent on how you access the arguments.
Its entirely up to you how you handle arguments passed to your function, so its up to you.
If you want to check if an argument is null you use
if (myVar === null) {
and if you want to check if an argument is undefined you use
if (typeof myVar === "undefined") {
If the expected argument is anything other than 0, null or undefined, then you can check for this using
if (myVar) {
So whether or not your myFoo(null) should behave the same as myFoo(undefined) is entirely up to how you handle these internally.
When it comes to extra parameters, this has no effect other than the arguments collection being larger than expected.

Categories