Writing Testable Classes

Write Cohesively

Avoid long, complex functions with many side effects and interconnected pieces. Break them down into individual methods and flatten them to the class level (see below).

Flatten Functions

Avoid deeply nested functions. Wherever possible, move functions to the class level so they can be isolated and tested independently.

Deeply nested - hard to isolate:
init: function () {
    this.getBooksStore().on({
        scope: this,
        load: function(store, records) {
            Ext.defer(function() {
                if (records.length) {
                    var record = records[0],
                        me = this;

                    me.getBookSideBar().getSelectionModel().select(record);
                }
            }, 500, this);
        }
    });
}
Flattened - easy to isolate and test:
init: function () {
    this.getBooksStore().on({
        scope: this,
        load: this.onBooksStoreLoad
    });
},

onBooksStoreLoad: function (store, records) {
    Ext.defer(this.onBooksStoreDeferredLoad, 500, this, [records]);
},

onBooksStoreDeferredLoad: function (records) {
    if (records.length) {
        var record = records[0],
            me = this;

        me.getBookSideBar().getSelectionModel().select(record);
    }
}

Dynamic Configuration

While it may be necessary to use dynamic class configuration in some circumstances, having these outside a function adds significantly to the plumbing required to test the class. This usually requires creating fakes.

Wherever possible, move dynamic configuration from a definition's object literal to the body of an initialization function.
Note: The opposite is true for basic configuration. It is best pratice to have all basic configuration in the object literal rather than inside functions.

Inline dynamic configuration - requires setting up fakes before testing:
layout: {
    type : 'hbox',
    align: 'middle',
    pack : 'center',
    availableSpaceOffset: Ext.getScrollbarSize().width
}
Initializer dynamic configuration - no pre-testing fakes required:
layout: {
    type : 'hbox',
    align: 'middle',
    pack : 'center'
},

initComponent: function () {
    this.callParent(arguments);

    this.layout.availableSpaceOffset = Ext.getScrollbarSize().width;
}

Last edited Oct 9, 2012 at 9:22 AM by Qube, version 3

Comments

No comments yet.