问题
I'm finding it incredibly slow to fix issues that are specific to the iOS portion of my app. I'd like the know the recommended way to debug Worklight apps when the browser debugger isn't available.
In particular, I'm working on issues with WL.JSONStore which only works on iOS and Android. I can't use the browser debugger to see what's going on. When I do WL.Logger.debug() statements, nothing is showing up in the Xcode console, and the iPad simulator console (Cordova) only displays a few lines. There have also been periods this week that no output is printed anywhere.
I have downloaded and installed Weinre too, but none of the print statements appear to show up in its console and in general I just don't see information about the areas I need.
Thanks in advance for your suggestions.
回答1:
General Worklight 5.0.6 Debugging
- Look at the training module titled Debugging your applications. (Direct PDF link)
Debug Tips for JSONStore on Worklight 5.0.6
- Try
console.log('message')
orWL.Logger.debug('message')
insidejsonstore.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
orWL.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 withSELECT * FROM [collection-name];
. To exitsqlite3
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.
回答2:
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.
来源:https://stackoverflow.com/questions/15959693/what-are-the-recommended-ways-to-debug-worklight-applications