Recently I was working on some JavaScript that really needed unit tests. I was making a substantial change that could not introduce any regression bugs and is very difficult to black box test. After all, this JavaScript was live! After digging into it a bit, reading the JavaScript spec since I'm more familiar with other languages like C/C++, Java and C#, I came to the conclusion it was going to be difficult so set off on a journey to see how others did it so I could save myself some time reinventing the wheel. My Google search of "unit testing private methods javascript" resulted in coming across the blog post How to Unit Test Private Functions in JavaScript.
The solution provided by Philip Walton was pretty good, but has a couple caveats. First let me explain what his solution is so you don't have to go read his entire post before continuing. He concludes that there are two camps of testing private JavaScript methods:
1. Don't
2. Everything is public
Obviously that isn't so good so he came up with a new option:
3. Export the private methods so they are public but do it in such a way that a code stripper removes them before going live.
The code stripper option isn't much of a stretch because most JavaScript goes through a compression process anyway removing white space and comments. I like his option but for me it wasn't an option to be able to modify the code stripper. We use YUI Compressor and aren't going to modify it. We could add a preprocessor but that isn't an option at this point. Plus there is potential for bugs because the code that is live isn't the same as the code you are testing. Our stripper has been around for a long time so we have confidence in it. So I came up with a new option:
4. If a global variable has been introduced and the .js file is loaded from a specific URL then initialize the global variable with a closure class containing only the private methods you want to test. For example if the URL is contains "http://localhost" or "file://", then initialize the closure. Any URL could be added here, including an internal test URL. However I can see how publishing a private URL is undesirable no matter how difficult it is to read.
For example:
var myclass = function() {
// Private
function someInternalMethod(arguments) {
}
function anotherInternalMethod(arguments) {
}
function initialize() {
if ((typeof __myclassTestHook__ !== 'undefined') &&
(__myclassTestHook__ == null) &&
((window.location.href.indexOf('http://localhost') == 0) ||
(window.location.href.indexOf('file://') == 0))
) {
__myclassTestHook__ = {
someInternalMethod: someInternalMethod,
anotherInternalMethod: someInternalMethod,
};
}
}
// Public
function publicMethod(arguments) {
}
function anotherPublicMethod(arguments) {
}
initialize();
return {
publicMethod: somePublicMethod,
anotherPublicMethod, anotherPublicMethod
};
}();
Now:
Thursday, May 28, 2015
Unit Testing JavaScript
Posted by
Chris Bensen
at
6:00 PM
0
comments
Monday, May 4, 2015
Mountain Unicycling
Mountain Unicycling is the best sport I have every done. By far the most energy expended for the amount of time spent ratio. Check out this video if you are at all interested and want a challenge!
Posted by
Chris Bensen
at
7:00 AM
0
comments
Thursday, April 30, 2015
Homeland Security wants less Encryption
The full text of the speech given by the Remarks by Secretary of Homeland Security Jeh Johnson at the RSA Conference 2015 can be found here. I think it is very telling where Homeland Security is from this small except:
Posted by
Chris Bensen
at
7:00 AM
0
comments
Tuesday, April 28, 2015
Properties in C++ Part II
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: C++, Code, programming
Monday, April 20, 2015
Properties in C++
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: C++, Code, programming
Monday, March 30, 2015
Workout - Functional Patterns
The title says it all: "This is not CROSSFIT this is FUNCTIONAL PATTERNS". This is an extremely ergonomic and healthy way to workout. CrossFit is not safe. Seriously, it isn't. Most instructors are not knowledgable enough which is why CrossFit is so popular. It takes a few days to get a CrossFit certification. Lots of cling and jerky movements where as "Functional Patterns" is very round, front back side to side. Simply awesome!
Posted by
Chris Bensen
at
7:10 PM
0
comments
Labels: Lifestyle
Thursday, March 26, 2015
Exercises to do at your Desk
We now know that sitting all day isn't good for you. So here is a graphic with a bunch of desk-based exercises.
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: Lifestyle
Wednesday, March 25, 2015
Back from my Blog Hiatus
I had a run in with a few viruses and bacteria over the last few months and haven't posed much (one post I think). So, I'm just now getting some time and feeling up to the task of adding more content to this blog.
Posted by
Chris Bensen
at
6:19 PM
0
comments
Wednesday, February 18, 2015
C++ Ordered Map
The std::map class is not ordered. Coming from any other programming language with a nice standard library this seems like a serious hole in C++. Boost has one, but not everyone can use Boost. So, here is one a threw together. Sure it's missing things, but that's what you get for free. Enjoy!
#ifndef ORDEREDMAP_H
#define ORDEREDMAP_H
#include <map>
#include <vector>
#include <assert .h="">
template <typename _t1="" _t2="" typename="">
struct pair
{
typedef _T1 first_type;
typedef _T2 second_type;
first_type first;
second_type second;
pair(first_type Value1, second_type Value2) {
first = Value1;
second = Value2;
}
};
template <typename tkey="" tvalue="" typename="">
class OrderedMap {
public:
typedef TKey key_type;
typedef TValue mapped_type;
typedef pair<key_type mapped_type=""> container_type;
private:
typedef std::map<key_type container_type=""> map_type;
typedef std::vector<container_type> list_type;
map_type FMap;
list_type FList;
typename list_type::iterator FindListItem(const key_type Key) {
typename list_type::iterator result = FList.end();
for (typename list_type::iterator iterator = FList.begin(); iterator != FList.end(); iterator++) {
container_type *item = *iterator;
if (item->first == Key) {
result = iterator;
break;
}
}
return result;
}
public:
OrderedMap() {
}
~OrderedMap() {
for (typename list_type::iterator iterator = FList.begin(); iterator != FList.end(); iterator++) {
container_type *item = *iterator;
delete item;
}
}
void Append(key_type Key, mapped_type Value) {
container_type *item = new container_type(Key, Value);
item->first = Key;
item->second = Value;
FMap.insert(std::pair<key_type container_type="">(Key, item));
FList.push_back(item);
}
void Insert(size_t Index, key_type Key, mapped_type Value) {
container_type *item = new container_type(Key, Value);
item->first = Key;
item->second = Value;
FMap.insert(std::pair<key_type container_type="">(Key, item));
FList.insert(FList.begin() + Index, item);
}
void Remove(key_type Key) {
typename list_type::iterator iterator = FindListItem(Key);
if (iterator != FList.end()) {
FMap.erase(Key);
FList.erase(iterator);
}
}
void Remove(size_t Index) {
typename list_type::iterator iterator = FList.begin() + Index;
if (iterator != FList.end()) {
container_type* item = *iterator;
if (item != NULL) {
FMap.erase(item->first);
FList.erase(iterator);
}
}
}
mapped_type &operator[](key_type Key) {
container_type* item = FMap[Key];
assert(item != NULL);
if (item != NULL) {
return item->second;
}
throw std::out_of_range("Index out of range");
}
mapped_type &operator[](size_t Index) {
assert(Index >= 0 && Index < Count());
container_type* item = FList[Index];
assert(item != NULL);
if (item != NULL) {
return item->second;
}
throw std::out_of_range("Index out of range");
}
size_t Count() {
return FList.size();
}
};
#endif //ORDEREDMAP_H
Update: March, 25 2015 - The code was not escaped properly and didn't show up right. Now it should be better.
Posted by
Chris Bensen
at
7:00 AM
0
comments
Thursday, January 8, 2015
New Years Resolution #1 - Be More Healthy by Not Drinking Soda
If you stop drinking soda you will loose 5lbs in the first month. Seriously. Don't switch to diet soda, drink water instead.
Search Google and you'll come up with thousands of links such as the first three that support what I'm saying:
The-Daily-Cost-Of-Your-Soda-Habit
Want to Lose Weight Fast? Cut Out Soda from Your Diet
Can You Lose Body Fat by Stopping Drinking Soda?
If you replace it with anything that contains calories such as lemon aid it won't help. Replace the soda with water or maybe tea. Obviously the occasional soda is fine, but once you cut it out and water becomes your new habit, you won't be able to finish an entire 12oz soda. I have friends who have done this and it has worked for them. Make this your number one New Year's resolution and you won't be disappointed.
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: Lifestyle
Wednesday, December 31, 2014
New Years Resolutions
Every year millions of Americans declare New Year's resolutions. Here is a great article about how this whole tradition started:
The Surprising Reason We Make New Year's Resolutions
Since most people I know always have losing weight, staying fit and healthy and enjoying life on their list, I'm going to dedicate all my posts in January to things that I do (or wish I did) to satisfy a fit and healthy lifestyle. Everything will be published under a new label Lifestyle.
I'm also hoping to get my sister who is a physical therapist to write a few posts because she has a lot of extremely valuable detailed information from her education that most of us would only dream of knowing. Or maybe we wouldn't want to know because once you know you have to do things better!
So stay tuned and check back often because this should be fun!
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: Lifestyle
Tuesday, December 30, 2014
iOS Paralax
Posted by
Chris Bensen
at
7:00 AM
0
comments
Labels: iOS

