April 10, 2014

How to debug Yeoman generator

1. install node-inspector:

2. start Node Inspector server:

3. run node.js with Yeoman-cli in debug mode:

where 'MyGenerator' is Yeoman generator name which you want to debug.
On Windows "path\to\global\npm" is something like "C:\Users\{UserName}\AppData\Roaming\npm".

4. open Chrome or Opera (any Blink-based browser) and go to http://localhost:8080/debug?port=5858

November 11, 2013

Deploying 4.5 projects with WebDeploy: TargetFrameworkVersion vs managedRuntimeVersion

Recently we were migrating several of our ASP.NET projects onto .NET 4.5. For every project we have CI build in TeamCity. During TC-build we're building WebDeploy-package and deploying it onto our test server:
msbuild /t:Package path/to/project/WebServer.csproj
WebServer.csproj.deploy.cmd /p:WebPublishPipelineProjectName=WebServer /p:Configuration=Debug /p:DeployIisAppPath=site/app1

After migration our builds worked fine. But deployed applications did not. After investigating build logs we found out that deploying of all projects were failing since migration onto 4.5 - running generated deploy.cmd file failed with an error. Unfortunately cmd-file's exit code was 0 and TeamCity didn't understand that something broke.

The error was the following:
Error: (01.11.2013 13:25:23) An error occurred when the request was processed on the remote computer.
[13:25:23][Step 8/10] Error: The application pool that you are trying to use has the 'managedRuntimeVersion' property set to 'v4.0'. This application requires 'v4.5'.

"Why of course!", we thought. "We just need to update .NET". But .NET 4.5 was already installed on our server. We remember that 4.5 is "in-place upgrade" for 4.0 and it doesn't change .NET runtime version. So for AppPool in IIS we still have 4.0 as ".NET Framework version".
So what's the problem?

It seems that these's a bug in WebDeploy's tasks for msbuild.
After we build a project which targets v4.5 using msbuild's Package target we'll get a couple of files besides deploy.cmd: SetParamets.xml and SourceManifest.xml. The second one is a manifest file - parameters for manifest provider, which is generated by task ExportManifestFile from Microsoft.Web.Publishing.targets:

Unfortunately manifest file is generated incorrectly. As you can see in example above parameter managedRuntimeVersion for IisApp provider is set as "v4.5". Probably the msbuild task uses property TargetFrameworkVersion from csproj file as a source. But ".NET Framework version" in IIS AppPool can't have such value (because 4.5's runtime version is still 4.0).

To fix the problem just add DeployManagedRuntimeVersion property into your VS-project:

Obviously the bug will be fixed someday but at the moment of VS2013 RTM it's still actual.

October 23, 2013

VS2013 requires IE10 but IE10 installer requires Internet access

If you have VS-projects of VS-extensions (vsix) which you are building on a build server and want to migrate them onto VS2013 then you have a problem. To install VS2013 SDK you have to install full VS2013 first. To install VS2013 you have to install IE10. But if your build server doesn't have Internet access then IE10 won't install.

Here's KB with the list of patches which you need to install manually before installing IE10:


After installing patches and a reboot IE10 should install successfully.

September 23, 2013

Using NDepend for documenting breaking changes

I'm involved in building frameworks and libraries. When we're releasing a new version it's very important tell our users about all breaking changes. There could be different approaches in documenting them. It's very hard task really, especially for javascript code. The simplest approach I think is to mark issues in your bug tracking system as they have associated commits which introduced breaking changes.
But it gives only high level overview of breaking changes. Users would need detailed documentation on event API change which effects them.

Fortunately for .NET code (and Java) this problem can be solved with help of great tool for deep code analysis - NDepend. It's almost a decade old and it's kind of swiss army knife for code analysis. So I'm going to show only a small use-case how the tool can be used.

It will be next big version released soon (v5) with redesigned UI and many new features. But this post is applied to v4 also.

Using NDepend we can load a current version of assemblies and a previous version (named "baseline"). And then use LINQ-like Code Query Language to query again both versions.
Here's my CQL-query for displaying methods with breaking changes:

The query result can be exported into Html, Excel, Xml and Text.

The query isn't ideal indeed. Particularly it ignores changes in constructors signatures.

September 7, 2013

grunt-croc-qunit got support of code coverage via Istanbul

My story on migrating to Grunt continues.
In the previous post I decrbided my motivation on creating a new Grunt pluging - grunt-croc-qunit.

After I migrated all our unit tests onto grunt infrastructure I start migrating our code coverage. We used to be using JSCoverage for code coverage. For supporting JSCoverage we created a bunch of boilerplate scripts to inject into PhantomJS for gathering and generating coverage reports. Before jumping into rewriting all this stuff onto Grunt I decided to reevaluate code coverage engine choosing.
JSCoverage worked fine for us. But it doesn't have statements coverage (only lines coverage). Also it's stated on its homepage that its development is stopped and its successor is another library - JSCover. So rewriting code to reusing a library which stopped its development didn't seem to be a good idea for me. And I made a bit search on what js code coverage tools are popular nowadays. I ended with three libraries:

The first link in Google for the term "JSCover Istanbul Blanket" is this post. This blog post by John Ryding worth reading. John ended with choosing JSCover and mentioned that he liked Blanket also. JSCover is a Java-based tool. It's a drawback for me. So I started with Blanket first and spent some time trying to get it working.
Our use-case is to instrument sources and then run QUnit tests in PhantomJS with them using connect Web server. Dispite its motto "easy to install, easy to configure, and easy to use" I find it difficult to get it working in my use-case. It was unclear for me how to specify which AMD/RequireJS modules to instrument and how to extract coverage info from the browser.

So I turned to Istanbul. I found it's a really cool tool. Istanbul is a node module ("npm install Istanbul") so it can be used from Grunt tasks easily. Also it supports command line. So all I need is just to extract coverage info from within browser (PhantomJS) and save it into a file.

I decided to add support of Istanbul into grunt-croc-qunit plugin. But without adding direct dependency on Istanbul. So if you decided to use code coverage tasks then you'll need to install Istanbul first.

Plugin grunt-croc-qunit provides two additional tasks: coverageInstrument and coverageReport. The first one is for instrumenting code. It has similar to copy task options - you should specify "sources files" (what to instrument) in the same notation as grunt-contrib-copy and "destination" (where to save instrumented files).
The coverageReport task is for generating report. Obviously tests should be run between these tasks.

I've create a fully functional example of a project with tests and Grunfile with using of QUnit/Istanbul tasks - you can download it here.

The example Gruntfile contains 'testcoverage' composite task which is a pipeline for executing tasks: coverageInstrument, connect, qunit, coverageReport:

After you downloaded and extracted the archive you'll need to install all node modules:
npm install
Then just run:
grunt codecoverage
After tests completes you can find the coverage report in .tmp\coverageReports\html folder.
For more info on tasks options please check the readme on https://github.com/CrocInc/grunt-croc-qunit.

August 28, 2013

Issues with grunt-contrib-qunit/grunt-lib-phantomjs/phantomjs plugins and replace them with grunt-croc-qunit

For one of our client-side projects I decided to migrate on Grunt. Grunt is a awesome task-runner for client-side projects based on node.js/npm. We had some infrastructure for builds and tests running before. Therefore all our code should be migrated into Grunt infrastructure. Fortunately there're a lot of cool plugins for Grunt on http://gruntjs.com/plugins. A Grunt-plugin is just a npm module.
Our unit-tests uses QUnit. We run them in browser and under PhantomJS with a cmd-file.
There is an official Grunt plugin for running qunit tests under PhantomJS - grunt-contrib-qunit. This plugin uses another npm-module for running PhantomJS - grunt-lib-phantomjs. And this one in turn uses module phantomjs.
The module 'phantomjs' is just a wrapper which downloads PhantomJS executable on module installation. In runtime the module returns path to phantom's executable file (phantomjs.exe) which we need to run by ourselves. It's exactly how grunt-lib-phantomjs behaves:

So I started using the grunt-contrib-qunit plugin. After that I installed all required modules and setup Grunt tasks in my Gruntfile.js all my unit tests started to pass on my machine. Cool. Then I commited all my project code with node_modules folder into our VCS (TFS) and started a build on our build server (TeamCity). BTW there's a plugin for TeamCity for running Grunt tasks.
Unfortunately the build failed with the following error:
Testing http://localhost:9002/tests-runner.html Fatal error: spawn ENOENT

Such an error means that it failed to start a phantomjs.exe process. I put additional logging into grunt-contrib-qunit\node_modules\grunt-lib-phantomjs\lib\phantomjs.js before executing grunt.util.spawn method and saw path which is passed into it. It was the path on my local machine! Why?
It turned out that grunt-lib-phantomjs module constructs ABSOLUTE path to phantomjs's executable file on installation (!) and hard-codes it into js-file from which it's being returned on runtime (as 'path' module field). Unbelievable.
So it turns out that we can't put 'node_modules' folder into VCS to allow running tasks on build server or other machines without installing all npm packages. Keeping 'node_modules' folder in VCS can be very handy for building projects on a build server as it usually has no internet access. We could setup a private repository for all npm packages indeed and install them on every build on build-server but why should we do this?

So I came to conclusion that 'phantomjs' module isn't suitable for me. And therefore I can't use grunt-lib-phantomjs. And therefore I can't use grunt-contrib-qunit.
So I had to write my our Grunt plugin for running qunit tests under PhantomJS without direct reference to 'phatomjs' npm module. Meet grunt-croc-qunit.
Grunt-croc-qunit is a union of official grunt-contrib-qunit and grunt-lib-phantomjs plugins with phantomjs dependency stripped out. Also it has a tiny performance improvement for injected bridge.js script (see https://github.com/gruntjs/grunt-contrib-qunit/issues/44 for details).

Plugin grunt-croc-qunit has the same 'qunit' task with one additional option - phantomPath. It's path to phantomjs' executable. See examples of usage at https://github.com/CrocInc/grunt-croc-qunit#usage-examples.
To install PhantomJS you can continue to use 'phantomjs' npm module but it will be your project's dependency (devDependency) not plugin grunt-croc-qunit 's one. With grunt-croc-qunit you can easily commit 'node_modules' folder into VCS and/or share it between machines. Everything continue to work.

June 21, 2013

Passing JSON objects via addJavascriptInterface in PhoneGap/Cordova application

Given a SPA Web-application which we want to convert into a native Android application with PhoneGap/Cordova.

Let's consider that the Web application expects to find a global config object which injected onto the server in a SCRIPT-tag. So the server response contains something like this:

Obviously that JSON config isn't hardcoded in server code (nor in the View markup) but is being loaded from a file in runtime.
While migrating the app into Cordova we need to convert our markup into a html page ("index.html"). Obviously we won't put JSON config into this html page. Ideally it should be injected into the page in runtime. Here's how to do this.

Let's consider the config is a JSON text file "config.json":
  "root": "/myapp/",
  "appName": "My Application"
So let's put it into Android's "assets" folder:

Then in onCreate method of our Cordova-Activity we need to load the file from resources, parse it into JSON and pass into WebView.
To pass the object into client code we're using WebView's addJavascriptInterface method.

Method getConfigJsonString reads json-file from resources and return its content:

Then we parse it into JSONObject to pass to the client-side via addJavascriptInterface.
Pretty simple.
Unfortunately there're some subtle momemts.
What would you expect to see in javascript code as 'xconfig' globar variable?
I'd expect to see a normal JS-object with the same fields as in JSON ("appName", "root").
But it's not the case. In javascript code 'xconfig' will become an Object instance with no fields but with 'toString' method returning actual JSON string:

Not very clear right?

So to finally get actual config object in client code we have to parse it via JSON:

Interesting that if in Java code we pass String:
this.appView.addJavascriptInterface(jsonConfig.toString(), "xconfig");
nothing will change - client'll still get the same strange object.

But what if the client code is shared between Web-app and Cordova-app? JSON.parse for a normal object will fail with SyntaxError.
So I came up with the following bootstrap code: