What are the recommended ways to debug Worklight applications?

馋奶兔 提交于 2019-11-27 15:24:18
cnandreu

General Worklight 5.0.6 Debugging

Debug Tips for JSONStore on Worklight 5.0.6

  • Try console.log('message') or WL.Logger.debug('message') inside jsonstore.js and your code ([app-name].js, etc.). The output should show up in Xcode's console and Android's LogCat.
  • Reset the Simulator or Emulator and/or call WL.JSONStore.destroy().
  • Make sure you're running on a supported environment:
    • Android >=2.2 ARM/x86 Emulator or Devices
    • iOS >=5.0 Simulator or Device
  • Try turning encryption off (ie. do not pass a password to WL.JSONStore.init or WL.JSONStore.initCollection).
  • Look at the SQLite Database file generated by JSONStore. This only works if encryption is off.

    • Android:

      $ adb shell
      $ cd /data/data/com.[app-name]/databases/wljsonstore
      $ sqlite3 jsonstore.sqlite
      
    • iOS

      $ cd ~/Library/Application Support/iPhone Simulator/6.1/Applications/[id]/Documents/wljsonstore
      $ sqlite3 jsonstore.sqlite
      

    Try looking at the searchFields with .schema and selecting data with SELECT * FROM [collection-name];. To exit sqlite3 type .exit. Take a look at this StackOverflow question for an example.

  • (Android Only) Enable verbose JSONStore.

    adb shell setprop log.tag.jsonstore-core VERBOSE
    adb shell getprop log.tag.jsonstore-core
    
  • (iOS >=6.0 and Safari >=6.0 Only) Try to use the JavaScript debugger. Set break points inside jsonstore.js. Helpful lines:

    • Bridge to Native code:

      cdv.exec(options.onSuccess, options.onFailure, pluginName, nativeFunction, args);
      
    • Success Callbacks returning from Native code:

      deferred.resolve(data, more);
      
    • Failure Callbacks returning from Native code:

      deferred.reject(new ErrorObject(errorObject));
      
  • Write Proper Tests (Unit, Functional, Integration -- get test coverage). Here's a template that uses QUnit and Sinon.js to create a Sandbox environment where you can test how JSONStore handles different types of data/calls:

    <!DOCTYPE HTML>
    <html>
    
    <head>
        <title>JSONStore Test App</title>
        <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css">
        <script src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
        <script src="http://sinonjs.org/releases/sinon-1.6.0.js"></script>
        <script>
            //QUnit configuration flags, no need to change it.
            QUnit.config.requireExpects = true;
        </script>
    </head>
    
    <body id="content" style="display: none;">
    
        <!-- Test results will be appended to the div below, no need to make changes here. -->
        <div id="qunit"></div>
    
    <script>
    
    //Start Worklight
    WL.Client.init({connectOnStartup : false});
    
    //Hook into the deviceready event
    document.addEventListener("deviceready", onDeviceReady, false);
    
    //onDeviceReady will be called when JSONStore/Cordova is ready
    function onDeviceReady () {
    
        //Auto executing function that holds the test
        (function (jQuery) { //The variable jQuery is usable inside.
    
            //Mock WL.Client.invokeProcedure using a Stub.
            //This is only useful if you need to link a Worklight Adapter
            //to a JSONStore collection to reproduce your issue or bug.
            //API Doc: http://sinonjs.org/docs/#stubs
            var fakeAdapter = sinon.stub(WL.Client, "invokeProcedure", function (invocationData, options) {
    
                //DO NOT Create a real adapter, just mock the reponse here if it's relevant to the bug.
                var ADAPTER_RESPONSE = {invocationResult: {fakeKey: [{fn: 'carlos'}, {fn: 'mike'}]}};
                options.onSuccess(ADAPTER_RESPONSE);
            });
    
            //[**Explain your test here**]
            var EXPECTED_ASSERTIONS = 2; //every assertion is a deepEqual below.
            asyncTest('[**Meaningful title here**]', EXPECTED_ASSERTIONS, function () {
    
                //Destroy first to make sure we don't depend on state
                WL.JSONStore.destroy()
    
                .then(function () {
    
                    //[**Start writting your test here**]
                    //The test below is an example, it does the following:
                    // - Initializes a collection linked to a fake adapter (see stub above).
                    // - Checks if initialization worked by checking the collection name.
                    // - Loads data from the fake adapter (see stub above).
                    // - Checks if load worked by checking the number of documents loaded.
    
                    var collections = {
                        col1 : {
                            searchFields : {fn: 'string'},
                            adapter : {name: 'fakeAdapter',
                                load: {
                                    procedure: 'fakeProcedure',
                                    params: [],
                                    key: 'fakeKey'
                                }
                            }
                        }
                    };
    
                    return WL.JSONStore.init(collections);
                })
    
                .then(function (response) {
    
                    //Prep for your assertion
                    var ACTUAL_VALUE = response.col1.name;
                    var EXPECTED_VALUE = 'col1';
                    var COMMENT = 'Checking for the right collection name';
    
                    //Do your assertion using deepEqual
                    //API Doc: http://api.qunitjs.com/deepEqual/
                    deepEqual(ACTUAL_VALUE, EXPECTED_VALUE, COMMENT);
    
                    return WL.JSONStore.get('col1').load();
                })
    
                .then(function (response) {
    
                    //Prep for your assertion
                    var ACTUAL_VALUE = response; //load returns number of documents loaded
                    var EXPECTED_VALUE = 2; //two documents are returned by the fake adapter (stub)
                    var COMMENT = 'Checking if load worked';
    
                    //Do the assertion using deepEqual
                    deepEqual(ACTUAL_VALUE, EXPECTED_VALUE, COMMENT);
    
                    start();//call start() after you finish your test succesfully
                })
    
                .fail(function (error) {
    
                    deepEqual(false, true, 'Failure callback should not be called' + error.toString());
                    start();//call start() after you finish your test with a failure
                });
    
            });
    
        }(WLJQ)); //end auto executing function that holds the test
    
    } //end wlCommonInit
    </script>
    
    </body>
    </html>
    

Expected output of the code above:

Side-note: Here's a general article about the PhoneGap/Cordova workflow for a specific developer. There's a part of debugging, just browser-based though. Some of it applies to IBM Worklight development too.

cnandreu provides great tips here. Still, visibility is pretty poor and these approaches didn't really solve my problem. I would like to also suggest what I've found to be most useful in my project (aside from WL.Logger.debug() everywhere):

  • JSConsole has been indispensable (http://jsconsole.com/). In reality, I don't actually use it that much like it's intended. However, I've found that it's startup warning message does something with WL.Logger.debug() (and console.log()) that enables the statements to actually print to the console so I can see what I'm doing.

  • In iOS 6 Safari on the Mac lets you inspect the DOM of an attached device. It's moderately useful, especially for hybrid UI issues that only are misbehaving when running natively on iOS. I don't find it super helpful otherwise. See more at https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/DebuggingSafarioniPhoneContent/DebuggingSafarioniPhoneContent.html

  • The single most useful technique I've been using has been to write status messages to the UI. Yes, it's an ugly prehistoric way to do things, but everything else - including 80s error print statements to the console - have failed miserably. Here's what I do (using Dojo & JavaScript):

    var v = dom.byId('audio_status'); if (v) { v.innerHTML += "recording file ["+filename+"]"; }

Where audio_status is the ID of a DIV that displays the debug content.

This stuff is ugly, but at least we can see something.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!