从 0 构建自动化测试平台 (四) 文件上传与任务提交

关于网友推荐更好的方法

在第三篇中,关于前端页面的设计,陆续有网友给出了意见,其中有推荐一个工具:Pingendo,适合自主开发页面,有兴趣的网友可以自行体验下。


从 0 构建自动化测试平台 (四) 文件上传与任务提交_第1张图片

云测试平台要达到的效果

    和大多数的云测试平台一样,我们希望实现的效果是:将被测apk、ipa(甚至测试用例)上传,后台执行测试,然后在前端任务列表中查看对应的测试结果。这一过程大致经历8个过程:

1、被测文件上传
2、将文件路径传递给后端python
3、python根据路径和参数执行测试
4、python保存测试结果到数据库(如: rethinkdb)
5、前端发起查看测试报告的请求
6、Node.js从数据库中获取测试结果
7、Node.js将测试结果传递给前端
8、前端展示测试结果

我会逐一和大家介绍每一过程的具体实现:
文件上传
先上效果图:


从 0 构建自动化测试平台 (四) 文件上传与任务提交_第2张图片

前端实现

定义一个input输入框,我使用了第三方库dropzone实现拖拽,通过添加action来定义文件上传后要执行的动作,代码如下:

input#dropfile.dropzone(action='/file_upload', name='filename', readonly='readonly', placeholder='将电脑里的文件拖拽到此上传,小于100M的APK文件')

Node.js实现

在app.js中处理file_upload的post请求,代码如下:

/* 处理文件上传和保存 */
app.post('/file_upload', function (req, res) {
    log.info('文件上传:' + req.files);
    upload_file.save_app(req, res);
});

save_app的实现

读取前端传递过来的文件,然后写到指定目录uploads下,代码如下:

exports.save_app = function(req, res){
    var des_file = path.join(__dirname, '../../uploads', req.files[0].originalname);
    fs.readFile(req.files[0].path, function(err, data){  
        fs.writeFile(des_file, data, function(err){  
            if(err){
                var response = {
                    errcode:50004,
                    errmsg: err
                };
                log.info( response );
                res.send(JSON.stringify(response));
            }else{
                var response = {
                    errcode:0,
                    filename:req.files[0].originalname
                };
                log.info( response );
                res.send(JSON.stringify(response));
            }
        });
    });
};

这样就完成了文件的上传。

提交任务,移交到后端python执行测试

  创建一个任务,除了提交上传文件(被测app),可能还有其他参数,我们将所有参数写到表单form中。

前端实现

form#Step-Two-Div.Step-two(role='form', action='/upload/success', method='post')
//提交任务的按钮类型为submit,此处还定义了一个变量type,值为:compatibility
button.Blue-button(type='submit', name='type', value='compatibility ')
    | 提交任务

说明:提交任务时,会执行表单中的action,即发起 /upload/success请求,这里定义一个变量type是为了区分测试类型(如兼容性、稳定性),不同的任务都提交到/upload/success, Node.js端处理upload/succes的请求时通过判断type来区分测试类型,以便后端根据测试类型执行不同的python脚本。

Node.js实现

在app.js中处理/upload/succes的post请求,代码如下:

/* 处理提交参数 */
app.post('/upload/success', function (req, res) {
    log.info(req.body);
    var args = '';
    var type = '';

    if (req.body.filename === '' || req.body.filename === undefined) {
        var response = {
            errcode: 50001,
            errmsg: '请上传文件'
        };
        log.info(response);
        res.send(JSON.stringify(response));
        return;
    }

    if (req.body.email === '') {
        var response = {
            errcode: 50002,
            errmsg: '请填写邮箱地址'
        };
        log.info(response);
        res.send(JSON.stringify(response));
        return;
    } else {
        args += ' --email=' + req.body.email;
    }

    if (req.body.type !== undefined) {
        type = req.body.type;
        args += ' --test-type=' + type;
    }

    if (req.body.dev !== undefined) {
        args += ' --dev=' + req.body.dev;
    }

    if (req.body.monkey !== undefined) {
        args += ' --monkey=' + req.body.monkey;
    }

    apppath = path.join(__dirname, 'uploads', req.body.filename);

    fs.exists(apppath, function (exists) {
        if (!exists) {
            var response = {
                errcode: 50003,
                errmsg: apppath + ' 文件不存在'
            };
            log.info(response);
            res.send(JSON.stringify(response));
            return;
        } else {
            args += ' --app-path=' + apppath;
            log.info('args = ' + args);
            if (type == 'feedback' || type == 'versiontest'){
                args = apppath; // 数据分析模块只需要传递文件路径参数即可
                child_services.startAnalysis(type, args);
            }
            else {
                cmdqueue.inqueue(args);
            }

            rdb.findAll(function (tasks) {
                res.render('testmanager', {
                    "task_list": tasks
                })
            });

        }
    });
});

在这个方法里面,获取前端传递过来的文件路径req.body.filename、邮箱req.body.email、测试类型req.body.type,同时将这些参数放在args中,我们将args作为参数传递给child_process,child_process在调用python脚本时,将args传递给python。child_process中调用python脚本的代码如下:

var cmd = 'python devices.py' + args;
log.info('当前任务为:%s', cmd);
var child = child_process.exec(cmd, options);

cmd范例如下:

python vendor/comptest/devices.py --app-path=/home/K米4.6.6.apk [email protected] --test-type=compatibility

今天就暂时先写到这里,后续章节会持续更新,敬请期待……

有任何问题可以通过微信找到我,欢迎大家一起交流关于测试方面的问题。


从 0 构建自动化测试平台 (四) 文件上传与任务提交_第3张图片

你可能感兴趣的:(从 0 构建自动化测试平台 (四) 文件上传与任务提交)