如何用合金编写钛合金测试用例

时间:2016-10-13 05:24:37

标签: mocha appcelerator appcelerator-titanium appcelerator-alloy appcelerator-studio

我在编写合金框架的测试用例时遇到困难,因为我没有得到如何在mocha测试框架中使用控制器和合金文件。我搜索谷歌和下面的代码提示控制器的几个链接,但它抛出错误" TypeError:alloy.createController不是一个函数"。

var alloy = require(' ../../ alloy'); 它('验证行控制器',function(){

        console.log(JSON.stringify(alloy))
        var controller = alloy.createController('login', {
            name : "uniqueName",
        });

        // if(controller.passwordTest.value !== "uniqueName"){
        // throw new ("Verify row controller FAILED");
        // }
    });

2 个答案:

答案 0 :(得分:0)

目前,我可以向您展示我们代码库的一个(稍加修改)示例。

首先,我们的控制器测试是纯粹的javascript测试。所有对Ti api的调用都是针对模拟执行的。我们只专注于被测控制器,并且所有依赖都被模拟。

我们依靠jasmine和jasmine-npm。

  • 安装jasmine-npm;见https://github.com/jasmine/jasmine-npm
  • 在项目的根目录中创建'spec'文件夹(包含tiapp.xml的文件夹)
  • 将所有测试文件放在此文件夹中
  • 测试文件的文件名必须以_spec.js
  • 结尾
  • 从项目的根文件夹中运行jasmine命令

    describe('authenticate controller test',function(){

    var USER_NAME = "John Doe";
    
    var fooControllerMock = {
        getView: function(){}
    };
    
    var fooViewMock = {
        open: function(){}
    }
    
    
    Ti = {
        // create here a mock for all Ti* functions and properties you invoke in your controller
    }
    
    Alloy = {
        CFG: {
            timeout: 100
        },
        Globals: {
            loading: {
                hide: function(){}
            },
            networkClient: {
                hasAutoLogin: function(){}
            },
            notifications: {
                showError: function(){}
            }
        },
        createController: function(){}
    };
    
    var controllerUnderTest; // class under test
    
    $ = {
        btnAuthenticate: {
            addEventListener: function(){}
        },
        authenticate: {
            addEventListener: function(){},
            close: function(){}
        },
        username: {
            addEventListener: function(){},
            getValue: function(){}
        },
        password: {
            addEventListener: function(){}
        },
        windowContainer: {
            addEventListener: function(){}
        }
    };
    
    L = function(s){
        return s;
    };
    
    beforeEach(function () {
        controllerUnderTest = require('../app/controllers/auth');
    });
    
    
    
    it('should create foo controller when authentication was succesful', function(){
        spyOn(Alloy.Globals.loading, 'hide');
        spyOn(Alloy, 'createController').and.returnValue(fooControllerMock);
        spyOn(fooControllerMock, 'getView').and.returnValue(fooViewMock);
        spyOn($.username, 'getValue').and.returnValue(USER_NAME);
        spyOn($.auth, 'close');
    
        controllerUnderTest.test._onAuthSuccess();
    
        expect(Alloy.Globals.loading.hide).toHaveBeenCalled();
        expect(Alloy.createController).toHaveBeenCalledWith('foo');
        expect(fooControllerMock.getView).toHaveBeenCalled();
        expect($.auth.close).toHaveBeenCalled();
    });
    
    it('should show error message when a login error has occured', function(){
        spyOn(Alloy.Globals.loading, 'hide');
        spyOn(Alloy.Globals.notifications, 'showError');
    
        controllerUnderTest.test._onAuthLoginError();
    
        expect(Alloy.Globals.loading.hide).toHaveBeenCalled();
        expect(Alloy.Globals.notifications.showError).toHaveBeenCalledWith('msg.auth.failure');
    });
    
    });
    

请务必为您在控制器中调用的所有Ti *内容编写模拟实现(只是空)。我知道这很麻烦,但解决方案就是这样。

请注意,我们已经创建了一个npm包,它包含一个生成的模拟(基于api.jsca),以及一些代码,您可以使用这些代码模拟所有必需的依赖项,以及一组测试最佳实践。但是,在我们开源之前,我们将在内部验证此代码。我希望我们可以写几篇博文,并在几周内公开我们随附的github回购。只要留意tiSlack。

控制器代码:

function _onAuthSuccess() {
    Alloy.Globals.loading.hide();
    Alloy.createController('foo').getView().open();
    $.authenticate.close();
}

function _onAuthLoginError() {
    Alloy.Globals.loading.hide();
    Alloy.Globals.notifications.showError(L('msg.auth.failure'));
}

function _onAuthTokenValidationFailure() {
    Alloy.Globals.loading.hide();
}

function _authenticate() {
    var username = $.username.value;
    var password = $.password.value;

    if(Alloy.Globals.validationEmail.isValidEmailAddress(username)){
        Alloy.Globals.loading.show(L('authenticate.msg.logging.in'), false);
    } else {
        Alloy.Globals.notifications.showError(L('app.error.invalid.email'));
    }
}

function _onNetworkAbsent() {
    Alloy.Globals.loading.hide();
    Alloy.Globals.notifications.showError(L('global.no.network.connection.available'));
}

function _hideKeyboard() {
    $.username.blur();
    $.password.blur();
}

function _focusPassword() {
    $.username.blur();
    $.password.focus();
}

function _init() {
    Ti.App.addEventListener('auth:success', _onAuthSuccess);
    Ti.App.addEventListener('auth:loginFailed', _onAuthLoginError);
    Ti.App.addEventListener('app:parseError', _onAppParseError);
    Ti.App.addEventListener('network:none', _onNetworkAbsent);

    $.btnAuthenticate.addEventListener('click', ..);
    $.authenticate.addEventListener('close', _cleanup);
    $.username.addEventListener('return', _focusPassword);
    $.password.addEventListener('return', _authenticate);

    $.windowContainer.addEventListener('touchstart', _hideKeyboard);
}

_init();

function _cleanup() {
    Ti.API.info('Closing and destroying the auth controller');
     ... 
    $.windowContainer.removeEventListener('touchstart', _hideKeyboard);

    $.destroy();
    $.off();
    }

    module.exports = {
    test: {
        _onAuthSuccess: _onAuthSuccess,
        _onAuthLoginError: _onAuthLoginError
        }
    }

和相应的观点:

<Alloy>
    <Window>
        <View id="windowContainer">
            <TextField id="username" />
            <TextField id="password" >
            <Button id="btnAuthenticate" />               
        </View>
    </Window>
</Alloy>

答案 1 :(得分:0)

Titanium内部使用Ti-Mocha为其所有组件编写单元测试。它是Mocha的修改版本,使用测试套件,测试用例,链接以及更多来测试合适的代码覆盖率。试一试!