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

Mocha testing in Titanium(en)

Mocha testing in Titanium(en)

Avatar for Kosuke Isobe

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