Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mocha testing in Titanium(en)

Mocha testing in Titanium(en)

Kosuke Isobe

August 04, 2015
Tweet

More Decks by Kosuke Isobe

Other Decks in Programming

Transcript

  1. My projects w k0sukey/alloy-smelter Helper commands for Appcelerator Titanium MVC

    Framework Alloy project app w k0sukey/tss-formatter .tss files formatter, order, beautifier for your coding standards in Titanium Alloy

  2. As for testing in Titanium • Not easy to test

    • Simulator/Emulator or devices are required • Test in Appcelerator Platform is very expensive • Need Unit Test
  3. There are some.. • jshint • jsbeautifier • This is

    NOT • This is syntax check. It’s NOT test. // gulplfile.js var gulp = require(‘gulp’), plugin = require(‘gulp—load—plugins’)(); gulp.task(‘jshint’, function(){ return gulp.src(‘app/controllers/**/ *.js’) .pipe(plugin.jshint()) .pipe(plugin.jshint.reporter(‘jshint— stylish’)) .pipe(plugin.jshint.reporter(‘fail’)); }); gulp.task(‘jsbeautifier’, function(){ return gulp.src(‘app/controllers/**/ *.js’) .pipe(plugin.jsbeautifier({ logSuccess: false, mode: ‘VERIFY_ONLY’ })); });
  4. Challenges • No Titanium API in execution environment (Node.js) •

    Automatic testing would be Cool. • As for iOS version, Mac is required. • Now Titanium SDK 4.1.0.GA support Windows Native. But I don’t have Windows machine.
  5. VM module • In a simple term, It’s like Safe

    eval • Make new context, and execute JavaScript code in that sandbox • No exports or require at all
  6. VM module • Making new context like this. • Return

    value of vm.runInContext is the context of the execution result (≒Assertion!) var vm = require(‘vm’), context = vm.createContext({ require: require, module: module, exports: exports, console: console, setTimeout: setTimeout, setInterval: setInterval, clearTimeout: clearTimeout, clearInterval: clearInterval, JSON: JSON, alert: function(e) { console.log(e); } }), result = vm.runInContext(‘console.log(\’ Hello, world.\’);’, context);
  7. VM module • What if giving Titanium API to vm.createContext,

    does it work? • It might work! But I have to add all Titanium APIs var vm = require(‘vm’), context = vm.createContext({ Ti: { UI: { createWindow: function(){} } } }), result = vm.runInContext(‘var win = Ti.UI.createWindow();’, context);
  8. Titanium API • How many APIs? • The objects can

    not be set to the return value • Too much work to add them manually • Scraping the references?
  9. Titanium API • Titanium faker API will be created automatically

    using reference JSON, which execute in sandbox on Node.js • What if sending this API to VM module…
  10. ti-slag • Titanium faker API • Simulate the behaviors of

    Titanium API on Node.js without Titanium SDK • The exception error can be sent when the deprecated properties or methods are found • No screen transitions. Of course there is no screens!
  11. slagʁ • Slag is the glass-like by-product left over after

    a desired metal has been separated (i.e., smelted) from its raw ore. (via Wikipedia) • That is “Left over”.
  12. Mocha testing in ti-slag • Install the npm packages •

    Adding the test script in package.json $ cd path/to/yourapp $ npm init $ npm install mocha ti—slag lodash ——save—dev package.json { … “scripts”: { “test”: “mocha test.js” }, … }
  13. Mocha testing in ti-slag • At first alloy compiling. “ti

    build”/“appc run” are also OK. • The point is exporting the code under resources folder. • Then, “npm test” $ alloy compile ——config platform=ios $ npm test > [email protected] test /Users/ Kosuke/src/sandbox > mocha test.js iOS index.js ✓ should does not throw exception in the Controller 1 passing (10ms)
  14. Mocha testing in ti-slag • Alloy project will be compiled

    and the optimized classic code will be exported under Resources folder. • The result will be returned as the context, when the code was sent to ti-slag and executed in VM environment. • Compiled alloy controller is module.exports and has been seen. So execute this.
  15. // Resources/…/index.js function Controller() { function doClick() { var next

    = Alloy.createController(‘next’ ), view = next.getView(); view.open(); } $.index.open(); } module.exports = Controller; // app/controllers/index.js function doClick() { var next = Alloy.createController(‘next’) , view = next.getView(); view.open(); } $.index.open(); Mocha testing in ti-slag
  16. Mocha testing in ti-slag // test.js var _ = require(‘lodash’),

    assert = require(‘assert’), path = require(‘path’), slag = require(‘ti—slag); describe(‘iOS index.js’, function(){ var context = slag(‘./Resources/iphone/alloy/controllers/index.js’, { titanium: ‘4.0.0.GA’, platfrom: ‘ios’, module: { alloy: alloy, ‘alloy/controllers/BaseController’: BaseController } }); it(‘should does not throw exception in the Controller’, function(){ assert.doesNotThrow(function(){ context.Controller(); }); }); });
  17. Mocha testing in ti-slag • You may notice the second

    argument “module”. • If you set the module name to require here, it’ll be loaded. Enjoy! var context = slag(‘./ Resources/iphone/alloy/ controllers/index.js’, { titanium: ‘4.0.0.GA’, platfrom: ‘ios’, module: { ‘ti.map’: { // ࣗ෼Ͱ͕Μ͹Ε } } });
  18. Mocha testing in ti-slag • Alloy works under Titanium SDK

    • Alloy works under ti-slag like Titanium SDK • It’s OK to send Alloy context to ti-slag’s module(BaseController.js will be needed as well) • Refer k0sukey/ti-slag/test.js for detail
  19. Mocha testing in ti-slag • The method in Alloy Controller

    can be used without any changes, because Alloy context will be deployed in ti-slag • To have EventListener using add/get/remove events which are added in [email protected] assert.doesNotThrow(function(){ context.Controller(); var listeners = context.getListener(); });
  20. Mocha testing in ti-slag describe(‘iOS index.js’, function(){ var context =

    slag(‘./Resources/iphone/alloy/controllers/index.js’, { titanium: ‘4.0.0.GA’, platfrom: ‘ios’, module: { alloy: alloy, ‘alloy/controllers/BaseController’: BaseController } }); it(‘should does not throw exception in the Controller’, function(){ assert.doesNotThrow(function(){ context.Controller(); }); }); it(‘should does not throw exception in the event listeners’, function(){ assert.doesNotThrow(function(){ _.each(context.getListener(), function(listener){ listener.handler(); }); }); }); });
  21. circle.yml • test:pre: 
 gulp jshint/jsbeautifier
 After that,
 Alloy compiling

    • Getting the result of compiling, execute test machine: node: version: 0.10.34 dependencies: pre: — npm install —g alloy — npm install test: pre: — gulp jshint — gulp jsbeautifier — alloy compile ——config platform=ios — alloy compile ——config platform=android
  22. 1. Push to GitHub 2. Execute on CircleCI 3. Send

    the result to 
 Slack
 
 ɹɹɹɹɹɹɹɹɹ 4. I’m Happy! CI