White-box testing in Javascript - how to deal with privacy? - javascript

I'm writing unit tests for a module in a small Javascript application. In order to keep the interface clean, some of the implementation details are closed over by an anonymous function (the usual JS pattern for privacy). However, while testing I need to access/mock/verify the private parts.
Most of the tests I've written previously have been in Python, where there are no real private variables (members, identifiers, whatever you want to call them). One simply suggests privacy via a leading underscore for the users, and freely ignores it while testing the code. In statically typed OO languages I suppose one could make private members accessible to tests by converting them to be protected and subclassing the object to be tested. In Javascript, the latter doesn't apply, while the former seems like bad practice.
I could always fall back to black box testing and simply check the final results. It's the simplest and cleanest approach, but unfortunately not really detailed enough for my needs.
So, is there a standard way of keeping variables private while still retaining some backdoors for testing in Javascript?

No. I don't believe there is. It basically boils down to whether you take the closure approach and relinquish white box tests or do white box tests and use name decoration for "private" members. Actually not only in Python, but in javascript too many projects use the not so magic underscore to decorate privates. So in a way this is already a widely accepted solution to the problem.
If you don't want that and really, really need white-box unit testing, then you can always integrate the tests into your objects. If you have a separate build step for production code (minimization, require/provide-resolution, etc) then you can remove the test functions in this process.

Related

Is JavaScript compatible with strict Page Object Pattern?

I have built various Test Automation frameworks using the Page Object Pattern with Java (https://code.google.com/p/selenium/wiki/PageObjects).
Two of the big benefits I have found are:
1) You can see what methods are available when you have an instance of a page (e.g. typing homepage. will show me all the actions/methods you can call from the homepage)
2) Because navigation methods (e.g. goToHomepage()) return an instance of the subsequent page (e.g. homepage), you can navigate through your tests simply by writing the code and seeing where it takes you.
e.g.
WelcomePage welcomePage = loginPage.loginWithValidUser(validUser);
PaymentsPage paymentsPage = welcomePage.goToPaymentsPage();
These benefits work perfectly with Java since the type of object (or page in this case) is known by the IDE.
However, with JavaScript (dynamically typed language), the object type is not fixed at any point and is often ambiguous to the IDE. Therefore, I cannot see how you can realise these benefits on an automation suite built using JavaScript (e.g. by using Cucumber).
Can anyone show me how you would use JavaScript with the Page Object Pattern to gain these benefits?
From Gerrit0's comment above and investigating it further, it seems a great way to achieve this is to use TypeScript (which is a statically typed version of JavaScript):
https://en.wikipedia.org/wiki/TypeScript
I am not much about this patterns.but i will give some details maybe it helps to you.
http://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html
http://www.assertselenium.com/automation-design-practices/page-object-pattern/
It seems a great way to achieve this is to use TypeScript (which is a statically typed version of JavaScript):
https://en.wikipedia.org/wiki/TypeScript
If you use Jetbrains products like IntelliJ IDEA it will do a code completion and ther proper navigation for you. In javascript world page object is a known pattern too. AngularJs offers it too in it's own e2e test framework (http://www.protractortest.org/#/page-objects). Personally I use IIFE for page objects and IntelliJ does the rest. If it doesn't fit to your needs you can still choose typescript and transpile it to javascript.

JavaScript type checking and exceptions in the context of Prototype constructors?

I'm building my first open-source JavaScript library as a node module, it's solving a very simple problem and thus it's a very simple module, specifically, it is a single prototype object.
To offer context, I'm from a purely web-tech background and only in the past year have I started to look into other languages, falling in love with statically typed, truly OOP and class-oriented languages and I'm beginning to see the breadth of pros and cons for the languages on either side of the camp.
As far as I understand, when constructing a class with class-oriented you should return nil to specify that construction has failed allowing a user to check with if(instance === nil) for it's success. Alternatively I've seen return 421 for example to provide an error code, I then also assume some also return string e.t.c. But importantly, I've seen that you shouldn't throw an exception.
Is this correct? Also what are the reasons for that? Is this also a problem with prototype-oriented languages or does javascript's dynamic nature make it acceptable?
This leads onto my next question, I've seen a lot of javascript libraries over the years, had a tinker and whatnot. I've found that it's rare to not only to build prototypes in an OOP-ish pattern but it's also rare to come across any frequently implemented type detection or type checking, many people are relying on the convenience of the dynamic typing to offer that productivity boost, but I'd like to mix up the pros and cons of each type system by starting with dynamically typed but also introduce a more stable architecture using some statically typed patterns and methodologies.
To get to the point, is it an acceptable (or even good?) practice to heavily type check javascript scripts? I would love to add serious type checking code to my prototypes constructor and methods but as it's an open-source project I'm worried how the community will approach it, would they want it to be more dynamically typed? I can only assume many people use dynamically typed languages for their... uhh.. dynamic typing, but its worth a ponder.
DISCLAIMER
I understand have seen that many people say javascript is "untyped" rather than "dynamically" typed, but using dynamic purely for its proliferation.
TLDR-Q1: Can I throw exceptions in constructor methods? What about in javascript prototypes? Why!? How should I handle it?
TLDR-Q2: Can I introduce heavy type checking and throw exceptions to give javascript scripts a poor mans static type? Do developers like this? Am I being ignorant and this a really common thing?
TLDR-Q1: Can I throw exceptions in constructor methods? What about in
javascript prototypes? Why!? How should I handle it?
Yes, you can throw exceptions in a constructor. If truly invalid arguments have been passed, then that is probably the cleanest way to do things.
I, myself, would not generally design an expected path of the code to throw an exception, but would instead reserve it for the type of error that probably signifies bad data or wrong usage by the programmer. Exceptions get logged nice and cleanly in the debug console and are one of the quickest ways to communicate to someone using your constructor that they've messed up as it will get logged and you can put a nice descriptive message in the error object when you throw and the developer gets a stack trace.
Returning null is not such a clean or helpful way and adds code the developer probably doesn't normally need to check for null all the time.
TLDR-Q2: Can I introduce heavy type checking and throw exceptions to
give javascript scripts a poor mans static type? Do developers like
this? Am I being ignorant and this a really common thing?
You can write Javascript type checking as much as you need. IMO, you should only do so when you're trying to determine if an argument passed in is valid or not. If you need a string and the developer passes in a number and a numeric string is a reasonable input for the function, then I don't see why you should not just use Javascript's string conversion automatically and let things go.
Javascript developers like type checking when it helps them identify a mistake they've made. Javascript developers don't like type checking when it's just being pedantic and an auto or explicit type-conversion would have worked just fine.
Also keep in mind that you should rarely insist that a passed object is a particular type of object (say using instanceof) because it should be perfectly valid to pass any object that works like the expected object. For example, a promise in Javascript can pretty much be any object that has the desired methods that follow the proper specification. It does not have to be one particular type of object class with one particular constructor.
Javascript isn't a strongly typed language and there really is no reason to try to make it behave like it is something that it isn't. Check types when that's required for the proper operation of your code, not because you're trying to make Javascript behave as strictly as Java. I wouldn't suggest adding type checking just because you think all languages should have type checking. If that's your line of thinking, then perhaps you should write in TypeScript or something like that that adds type specification to the language.

Is the size of a JavaScript object affected by the number of methods in the (GWT) base-class?

I'm currently designing some API that will eventually be used in GWT, and I'm wondering if the number of methods in a Java class affects the size of an individual Object instance in JavaScript, after compiling the Java code using GWT.
Expressed another way, if I have an abstract base class with say 200 methods, and then sub-classes that override 2 of those, will the "cost" (memory usage) of those 200 methods be paid once for the application, or once per subclass instance?
In Java, the number of methods does not affect the Object size, but I don't know how this works in JavaScript.
The "200" number comes from trying to work-around the lack of Reflection in GWT, but I'd still be interested in the answer even if there was a way to get "fake reflection".
For this kind of question, there will not be an answer on Stackoverflow that beats your own experiments:
Write a class with 200 methods, then write one that subclasses it and overrides 2 methods. Compare JS code sizes to get a basic idea (though this is not the same as instance sizes). Use the Compile Report to get a better understanding. Then try compiling with style PRETTY or DETAILED, open the result in an editor, and verify if the generated code reuses methods or not. (Maybe also try it in OBFUSCATED mode to be sure).
Or, instantiate lots of objects, and inspect memory usage (several browsers offer tools, e.g. https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling)
Generally, make sure that your methods do get called at all - otherwise, the compiler will optimize them away.

How can I prove that my JavaScript files are in the scope of a specific JS or ECMA version?

Let's say you would get a bunch of .js files and now it is your job to sort them into groups like:
requires at least JavaScript 1.85
requires at least E4X (ECMAScript 4 EX)
requires at least ECMAScript 5
or something like this.
I am interested in any solution, but especially in those which work using JavaScript or PHP. This is used for creation of automated specifications, but it shouldn't matter - this is a nice task which should be easy to solve - however, I have no idea how and it is not easy for me. So, if this is easy to you, please share any hints.
I would expect something like this - http://kangax.github.com/es5-compat-table/# - just not for browsers, rather for a given file to be checked against different implementations of JavaScript.
My guess is, that each version must have some specifics, which can be tested for. However, all I can find is stuff about "what version does this browser support".
PS: Don't take "now it is your job" literally, I used it to demonstrate the task, not to imply that I expect work done for me; while in the progress of solving this, it would be just nice to have some help or direction.
EDIT: I took the easy way out, by recquiring ECMAScript 5 to be supported at least as good as by the current FireFox for my projekt to work as intendet and expected.
However, I am still intereseted in any solution-attemps or at least an definite answer of "is possible(, with XY)" or "is not possible, because ..."; XY can be just some Keyword, like FrameworkXY or DesignPatternXY or whatever or a more detailed solution of course.
Essentially you are looking to find the minimum requirements for some javascript file. I'd say that isn't possible until run time. JavaScript is a dynamic language. As such you don't have compile time errors. As a result, you can't tell until you are within some closure that something doesn't work, and even then it would be misleading. Your dependencies could in fact fix many compatibility issues.
Example:
JS File A uses some ES5 feature
JS File B provides a shim for ES5 deficient browsers or at least mimics it in some way.
JS File A and B are always loaded together, but independently A looks like it won't work.
Example2:
Object.create is what you want to test
Some guy named Crockford adds create to Object.prototype
Object.create now works in less compatible browsers, and nothing is broken.
Solution 1:
Build or find a dependency map. You definitely already have a dependency map, either explicitly or you could generate it by iterating over you HTML files.
Run all relevant code paths in environments with decreasing functionality (eg: ES5, then E4X, then JS 1.x, and so forth).
Once a bundle of JS files fail for some code path you know their minimum requirement.
Perhaps you could iterate over the public functions in your objects and use dependency injection to fill in constructors and methods. This sounds really hard though.
Solution 2:
Use webdriver to visit your pages in various environments.
Map window.onerror to a function that tells you if your current page broke while performing some actions.
On error you will know that there is a problem with the bundle on the current page so save that data.
Both these solutions assume that you always write perfect JS that never has errors, which is something you should strive for but isn't realistic. This might; however, provide you with some basic "smoke testing" though.
This is not possible in an exact way, and it also is not a great way of looking at things for this type of issue.
Why its not possible
Javascript doesn't have static typing. But properties are determined by the prototype chain. This means that for any piece of code you would have to infer the type of an object and check along the prototype chain before determining what function would be called for a function call.
You would for instance, have to be able to tell that $(x).bind() o $(x).map are not making calls to the ecmascript5 map or bind functions, but the jQuery ones. This means that you would really have to parse out the whole code and make inferences on type. If you didn't have the whole code base this would be impossible. If you had a function that took an object and you called bind, you would have no idea if that was supposed to be Function.prototype.bind or jQuery.bind because thats not decided till runtime. In fact its possible (though not good coding practice) that it could be both, and that what is run depends on the input to a function, or even depends on user input. So you might be able to make a guess about this, but you couldn't do it exactly.
Making all of this even more impossible, the eval function combined with the ability to get user input or ajax data means that you don't even know what types some objects are or could be, even leaving aside the issue that eval could attempt to run code that meets any specification.
Here's an example of a piece of code that you couldn't parse
var userInput = $("#input").val();
var objectThatCouldBeAnything = eval(userInput);
object.map(function(x){
return !!x;
});
There's no way to tell if this code is parsing a jQuery object in the eval and running jQuery.map or producing an array and running Array.prototype.map. And thats the strength and weakness of a dynamically typed language like javascript. It provides tremendous flexibility, but limits what you can tell about the code before run time.
Why its not a good strategy
ECMAScript specifications are a standard, but in practice they are never implemented perfectly or consistently. Different environments implement different parts of the standard. Having a "ECMAScript5" piece of code does not guarantee that any particular browser will implement all of its properties perfectly. You really have to determine that on a property by property basis.
What you're much better off doing is finding a list of functions or properties that are used by the code. You can then compare that against the supported properties for a particular environment.
This is still a difficult to impossible problem for the reasons mentioned above, but its at least a useful one. And you could gain value doing this even using a loose approximation (assuming that bind actually is ecmascript5 unless its on a $() wrap. Thats not going to be perfect, but still might be useful).
Trying to figure out a standard thats implemented just isn't practical in terms of helping you decide whether to use it in a particular environment. Its much better to know what functions or properties its using so that you can compare that to the environment and add polyfills if necessary.

Why does eval() exist?

Many programmers say it is a bad practice to use the eval() function:
When is JavaScript's eval() not evil?
I'd like to take a moment to address the premise of your question - that eval() is "evil"...
Is this eval() dangerous?
Buggy evaled code can violate security properties just as easily as buggy source code...
Why not eval() JSON?
There are a number of ways that your security may be compromised...
Is there ever a good reason to use eval()?
Yes - when there is no other way to accomplish the given task with a reasonable level of clarity... This eliminates 99% of cases where eval is used...
Why is eval unsafe in javascript?
The danger of eval only rears its ugly head when you are serving a script written by alice to user bob for bob's browser to eval...
So why does it exist in the first place?
Because sometimes there is a need. All the same reasons for/against using eval in JavaScript can likely be shared with the use of reflection in Java, for example.
However, I agree with everything you quoted in your question. Many reasons for using it are ill-advised, and best done differently - but sometimes, there is still a need, or it is simply the "best choice" over other available alternatives. (I'd focus on the answers to Is there ever a good reason to use eval()? for additional reasons.)
+1 to your question for good research.
eval() exists because sometimes you want to give complete programmatic control of your application to code passed in at run time.
Languages without an eval() feature can definitely provide (a subset? all?) of this functionality by asking each programmer to essentially write their own eval() -- lex the input, parse the input, create new objects as necessary, run methods or functions on them via simple string comparisons or similar. In essence, duplicate the entire interpreter that already exists and is debugged and fast.
Eval is actually a powerful feature and there are some things that are impossible to do without it. For example:
Evaluate code received from a remote server. (Say you want to make a site that can be remotely controlled by sending JavaScript code to it?)
Evaluate user-written code. Without eval, you can't program, for example, an online editor/REPL.
Creating functions of arbitrary length dynamically (function.length is readonly, so the only way is using eval).
Loading a script and returning it's value. If your script is, for example, a self-calling function, and you want to evaluate it and get it's result (eg: my_result = get_script_result("foo.js")), the only way of programming the function get_script_result is by using eval inside it.
Re-creating a function in a different closure.
And anything else you'd want to do that involves creating code on the fly.
The reason it is considered "evil" is because it's classicaly used by novices to do things that the language can handle natively. For example, the code below:
age_of_erick = 34;
age_of_john = 21;
person = "erick";
eval("console.log('age_of_"+person+"')");
And the code below:
age = {erick:34, john:21};
person = "erick";
console.log(age["erick"]);
Both do the same thing, except one parses a string, generates code from it, compiles into machine code and then runs, while the other reads a value from a hash, which is a lot faster.
There's a research publication exacty on this topic:
The Eval That Men Do -- A Large-scale Study of the Use of Eval in JavaScript Applications
Mirror on Wayback Machine
It is to me the most comprehensive answer to this question to date.
Quote from the abstract:
We have recorded the behavior of 337 MB of strings given as
arguments to 550,358 calls to the eval function exercised in over
10,000 web sites.
Amongst other, they identified 9 categories of recurring eval:
JSON - A JSON string or variant.
JSONP - A padded JSON string.
Library -One or more function definitions.
Read - Read access to an
object’s property.
Assign - Assignment to a local variable or
object property.
Typeof - Type test expression.
Try - Trivial
try/catch block.
Call - Simple function/method call.
Empty -
Empty or blank string.
A snippet from the conclusion (which is too long to be quoted entierly):
[...] While many uses eval were legitimate, many were unnecessary and
could be replaced with equivalent and safer code. We started this work
with the hope that it would show that eval can be replaced by other
features. Unfortunately our data does not support this conclusion.[...]
A paper well worth reading.
The eval() feature is like scissors. You're an adult, it's your responsibility to not run with them.
I've seen the design philosophy of dynamic languages (like JavaScript) summarised as preferring to enable smart people to do clever things above trying to prevent stupid people from doing silly things. (Unfortunately I can't recall the original source or phrasing.)
If you're worried about introducing bugs with eval, you can use strict mode. It seems to prevent some of the problems with how the feature is designed. (That is, as a "magic" function allowed to clobber your namespace.)
Eval exists to simplify tasks in JavaScript. You can use it evaluate multiple statements. Instead of having to find another way you can use eval to do such things. Even though it is discouraged it has considerable power and use.

Categories