JS Environment and Testing

Published December 18, 2015
Advertisement

[font=Arial][background=transparent]When I first tried my hand at programming something that employed real time rendering automated testing was not even a thing I was aware of. Sure I was a young lad at the time and had much to learn but the mention of writing a test was absent from any and every article I claimed as a learning resource. Working with web services and business development has taught me the great power that comes from automated testing, and this advantage has made my work increasingly better in quality. There still stands the simple fact that automated testing can not cover all quality cases of a product for example overall "user experience" (game quality?). [/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial]

[background=transparent]The Environment[/background]

[/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]It is my believe that in order to establish a quality control environment one must establish a development environment as well as a process that properly facilitates this quality control. It is certainly an achievement to implement quality control after a product is established. In my journey with WebGL there is no shortage of tools to use and I'm writing once again from my OS-X environment. My initial journal entry described the basic local development environment I use and with this going I have the ability to use a package manager and boost my WebGL project with other libraries.[/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]Install the Node Package Manager: with OS-X it's best to use homebrew for this otherwise your Linux package manager should have a recent version, and there is a Windows installer available.[/background][/font]
.brew install npmsudo apt-get install npmsudo yum install npm
[font=Arial][background=transparent]. [/background][/font]
[font=Arial][background=transparent]Once you have npm installed you will be able to create a "package configuration" for your JS project which contains many things, including any dependencies your application has. The package configuration is saved in a file in the root directory of your project called 'package.json' and we can generate this very easily.[/background][/font]
[font=Arial][background=transparent].[/background][/font]cd /to/your/projectnpm init # and follow the instructions...
[font=Arial][background=transparent]. [/background][/font]
[font=Arial][background=transparent]This will ask you some questions about your project (including Git remote repo location) and store this in the package.json file. Now that we have the configuration it's time to install the most important package for Node users, RequireJS (http://requirejs.org/). [/background][/font]
.
[font=Arial]

[background=transparent]Dependency Mangagement [/background]

[/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]As with many technologies the demands of a Javascript project are often tightly coupled with the client that is responsible for running that script. There is of course the most common use case of distributing JS to a browser from a web-server and running it on a client browser. Then there is the case of running it on a web-server and processing requests using the JS. More recently the language has found a way with being a client only language in that a local engine (such as Node) can be used to run JS for many purposes. With so many ways to use the language there is a challenge of managing the dependencies and libraries a project uses.[/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]A typical web application would simply load the Javascript from an HTML page that is delivered to the client. This is simple and the browser does all the work of requesting the resource and loading it in the browser. What about a library however, or a server side application? How are the different files and resources called upon loaded by the client that is to execute/use those resources? This is where a convention known as AMD comes in (Asynchronous module definition). This is a standard way of creating modules of code that can be loaded in an asynch. fashion in many different environments, including the client-side browser. Read more on the benefits of using AMD in your JS here - http://requirejs.org/docs/whyamd.html[/background][/font]
.
RequireJS is a library that complies to loading standard AMD and is very easy to configure for any environment including the client-side browser. This library has a "main entry point" that can be configured through an HTML tag, or simply called with a JS function.
.
First to install requireJS with NPM -
.npm install --save requirejs
.
This will install the library to the 'node_modules' directory local to your project, the --save option saves the dependency requirement to your local package.json (for easy distribution). Once installed you can include requireJS into ordinary HTML and define your main entry point with a script tag.
.[code=html:0]
.
Where the script in data-main is your entry point. This should look something like the following, but please do read through RequireJS documentation (http://requirejs.org/docs/start.html)
.[code=js:0]requirejs.config({ baseUrl: '/J3L'});requirejs(['J3L', './path/to/module-foo'], function(J3L, moduleFoo) { var testApp = new J3L.App("Test App"); var window = testApp.createWindow(800, 600); testApp.start();});
.
The initial call is to configure your environment and there are many options available here (again see the docs). The Requirejs method is what starts your application and the array included defines the dependencies your application needs. The function provided is a callback that is fired when those dependencies have finished loading.
.
In order to define a module you must follow the AMD convention, without going into detail this looks something like this:
.[code=js:0]define('FrameListener', ['./Class'], function(Class) { //Create some type of object to return that represents the "FrameListener" module var FrameListener = Class.extend({ init: function() {}, onUpdate: function() {} }); return FrameListener;});
.
The define function is key for AMD and defines information about your module including what dependencies are needed. These dependencies are "injected" into the callback method that follows making other modules instantly available by including them in the array/function callback.
.

To Test or Not To Test


.


While I've started establishing unit tests for the WebGL projects I've been working on, functional tests remain a mystery to me. The idea of writing a black box test against code that is so coupled with real time rendering seems daunting, but my mind tells me there has to be a way. The mass amount of research I have done is not promising and mostly generally points to a very specific solution to a very specific product. People will write bots that automate through the game and others capture rendering output as base64 and compare to future changes for automated regression. What has become quite clear is that black box integration/functional testing of real time rendering software is a giant black hole.
.
While I am learning how to use and manipulate WebGL/OpengL(ES) in every way possible, I will constantly be looking for a way to test the output of a system that is seemingly non-deterministic. Otherwise I have provided more fuel for an article series I keep promising, and this is the kind of thought out material that will be included. As always I want to provide an example that does more then get your feet wet, it gives you a serous nudge in how to gain the struts for a real time rendering application in place.
.
Until next time, Cheers!
3 likes 4 comments

Comments

tnovelli

And if the thought of installing random JS scripts as root troubles you, you'll soon end up at http://tnovelli.net/blog/blog.2011-08-27.node-npm-user-install.html (just about the only reason anyone visits my site :(). YMMV with OSX.

I did a lot of JS gamedev 3-4 years ago. WebGL wasn't usable, as it had serious driver/browser compatibility problems; supposedly it's better now. Requirejs/AMD will be a problem if it still has the timeout (people with slower connections can't load game); AFAIK that won't be solved until all browsers support html5 modules. Anyway, you're better off using a build script to pack all the JS into one file.

Tools:

https://github.com/tnovelli/apparition/blob/master/m - build script example

https://github.com/tnovelli/imgpack - simple JS sprite/texture packer

Good luck, you'll need it! :D

December 18, 2015 03:46 PM
roblane09

Thanks tnovelli, a lot of the stuff I'm playing with is pie in the sky, teach me the ropes kind of content. I think any production product would comply to a build system and take timeouts into consideration with it's audience. I'm really doing a lot of this to learn more about GL then JS, as I've been writing JS for the better part of 10 years.

<edit> do you have issues with uglify/build in development/debugging of your scripts? This is why I've been enjoying AMD/require the development is a breeze. </edit>

Browser support of HTML5 has certainly come a long way, and I expect it to continue improving so this all seems rather valuable to me in the end. The support is that of OpenGL ES but for a newbie to graphics rendering, it's more then enough.

That imgpacker is very nice btw, great work on that.

Cheers!

January 14, 2016 06:26 PM
roblane09

Also I always use local package management for npm as it's how I can distribute packages to remote destinations if I need to. This is similar to how I use other package managers such as ruby's bundle.

January 14, 2016 06:30 PM
tnovelli

Yes, uglifyjs sucks! I've used it for a few games but it's... funky. Try using the http://esprima.org/ libs instead. I haven't yet but @EDIgames has good things to say about it.

January 15, 2016 03:14 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement