• 浅论Javascript在汽车信号测试中的应用


    起因

    上周老板又给了我这个车辆工程毕业的码农一份工作:
    要我写一个测试台架出来。

    我先简单的分析了测试台架的几种典型的工况:
    1、发送一个CAN信号,测试能否查到。
    2、发送一个信号,是否能在规定时间内得到相应的回复
    测试用例可能有上千条,但是万变不离其宗,总而言之就是测试信号和一些功能是否正常,暂时不涉及节点的模拟和管理等。
    最后我采用.Net框架方便调用DLL(因为有很多硬件要对接),使用JS引擎实现测试的基础功能,使用JSON序列化数据。
    Winform+WPF控件实现界面,使用Python将已有的测试用例转换成代码。
    最后,实现了测试自动化的同时,允许测试人员对已有的用例进行修改,做到修改用例不用重新编译代码,开发和调试方便。

    思考

    那么我其实可以通过统一测试用例配置文件格式的方式来做:
    例如:
    TX(ID=123,Data=[1,2,3,4,5,6,7,8])
    WaitForRX(ID=124,Data[3]=0,timeout=5000ms)
    或者是
    {"TX",123,[1,2,3,4,5,6,7,8]}
    {"RX",5000,124,[?,?,?,0,?,?,?,?]}
    这种JSON格式的测试用例。最后提供一套测试用例的编辑、转换器,测试的同志就可以开心的使用了。
    但是,测试用例里又出现了这一种:
    While sending Signal XX in 50 Frame/Second, XXXXXXX
    这个时候我决心把常用的API暴露出来,形成一种新的语言,我们不妨称之为CAN控制语言,于是诞生了CAPL,我们给CAPL写了个IDE叫CANOE,成立了Vector公司,现在……
    咳咳,扯淡扯远了!
    我只是简单的把CAN收发的常用功能和一些IO,以及用户交互封装了一下,然后给了一个外壳,就可以完成各种测试任务了,那么软件剩下的部分其实是上千个测试脚本的管理,这个不复杂嘛,实在不行我们可以直接用Win的文件系统嘛!
    测试用例的不确定性导致了我下定决心使用脚本语言解决这个问题,让测试能足够的灵活,配置文件可管理,以后也能向后兼容。

    设计

    我初步设计,Javascript需要以下基础功能:
    1、程序的输出显示
    提供了log,print,alert等函数,看名字也知道是干嘛的了
    2、程序的输入:
    由于C#没有输入框,我单独写了一个InputBox,主要就靠这个输入。其次还提供了confirm函数来输入布尔值。
    3、程序的文件和网络IO
    使用get函数来获取URL中的数据,同时提供文件的读写和追加写入功能
    4、CAN的收发功能
    这里需要提供CAN信号的管理,CAN信号的发送和等待收取,以及CAN信号的周期后台发送、停止发送功能。这一部分才是核心。

    技术选型采用了C#,.NET 4。
    Javascript的引擎是Noesis.javascript,由于不需要太美观,所以使用Winform更加方便一点,再使用ElementHost融合一些WPF的控件,做到要灵活的地方能灵活,定死的地方开发快速。

    我对自己的技术选型还是很自信的,总而言之,我认为是做到了严肃活泼的地步。
    (但是对自己的界面美观程度很不自信……)
    最后IDE大概是这个样子的:

    IDE只是其中一个模块,但是是其中最强大功能模块了。

    JavaScript和C#的融合

    其实我当初想用Python作为融合的脚本语言的,但是考虑到JS引擎小巧,可以带在DLL里跑,最后还是选型了JS。
    JS的缺点非常明显,尤其是类型很弱这样的问题,使得开发API的时候一定要吃透JS和C#调用的规律。而且说来惭愧,因为这是测试任务,JS异步的特性在这里没有一点发挥(又跑题了)
    我在工程里新建了一个JavascriptEngine类,用来包装一个JS引擎,我这个程序所有的测试用例都只在一个容器中运行,减少开销。
    首先Import动态链接库

    using Noesis.Javascript;
    

    随后在类里新建一个静态的上下文(Context我也不知道怎么翻译比较好)

    static JavascriptContext ctx;
    

    随后在初始化代码中初始化:

    static JavaScriptEngine() {
        try {
            ctx = new JavascriptContext();
            //导入函数的js文件
            ctx.SetParameter("$", new JavaScriptUtility());
            runFile("UserLib.js");
        } catch (Exception e) {
            Logger.logError(e);
        }
    }
    

    这个时候可以加在一些你自己写的库函数和类,JavaScriptUtility是我写的一个用来承载常用函数的类,因为之前写jquery比较多,比较熟悉$符号,所以沿用了jquery的符号。
    这个时候我如果在JavaScriptUtility里新增一个函数:

    public class JavaScriptUtility {
        public static void alert(string queryInfo, string title) {
            MessageBox.Show(queryInfo, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
    

    这个时候你就可以在引擎中调用这个函数:

    ctx.Run("$.alert('Hello noesis.javascript','alert')");
    

    这个时候就可以看到你执行的代码。
    如果你想兼容风格,方便移植一些浏览器上写的代码可以这样:

    var alert = function(text,title){
        $.alert(text,title);
    };
    

    像这样封装一下就好,需要注意的是该引擎不支持胖括号的写法,你可以这么写:

    function alert(text,title){
        $.alert(text,title);
    };
    

    但是不能这么写:

    var alert = (text,title)=>{
        $.alert(text,title);
    };
    

    我已经踩过坑了,浏览器上好好的代码,上了Noesis就挂逼了,谁也不知道怎么回事。
    顺便说一下类型问题,类型系统还是比较智能的,比如你写了两个函数,第一个是

    void fun(object u);
    

    你又重载了一次:

    void fun(int u);
    

    这个时候如果你输入数字去调用,会调用第二个,输入字符串就会调用第一个。

    总结

    对于能固定下来的任务,不要想着使用脚本,使用脚本会增大使用人员的门槛,咱这里已经不讨论效率问题了,效率差100倍我也不惊讶。
    需要使用脚本引擎的是,变化大,而且往往以后也不能确定怎么改,而且可能随时要改的任务。
    脚本的通用性比较好,但是大多数从事汽车行业的人就算会写CAPL也不一定会JS。
    软件的编写,除了考虑个人的奋斗,也要考虑历史的进程啊!

  • 相关阅读:
    vc++ generate random via random_device and uniform_int_distribution
    Windows OpenGL 图像对比度调节
    OpenGL ES 版本介绍
    Windows OpenGL 图像伽马线
    Windows OpenGL 图像反色
    OpenGL ES 简介
    Windows OpenGL ES 图像饱和度调节
    修改 Docker 数据根目录
    mysql分库备份与分表备份
    docker dockerfile 映射端口范围 批量映射端口
  • 原文地址:https://www.cnblogs.com/TsingJyujing/p/6851580.html
Copyright © 2020-2023  润新知