精华内容
下载资源
问答
  • ROS节点

    千次阅读 2019-12-28 16:25:22
    ROS的世界里,最小的进程单元就是节点(node) 一个软件包里可以有多个可执行文件,可执行文件运行之后就成了一个进程(process),这个进程ROS中就叫做节点 从程序角度来说,node就是一个可执行文件(通常为C++...

    ROS节点介绍

    • 在ROS的世界里,最小的进程单元就是节点(node)
    • 一个软件包里可以有多个可执行文件,可执行文件在运行之后就成了一个进程(process),这个进程在ROS中就叫做节点
    • 从程序角度来说,node就是一个可执行文件(通常为C++编译生成的可执行文件、Python脚本)被执行,加载到了内存之中
    • 从功能角度来说,通常一个node负责者机器人的某一个单独的功能。由于机器人的功能模块非常复杂,我们往往不会把所有功能都集中到一个node上,而会采用分布式的方式,把鸡蛋放到不同的篮子里
    • 例如有一个node来控制底盘轮子的运动,有一个node驱动摄像头获取图像,有一个node驱动激光雷达,有一个node根据传感器信息进行路径规划,这样做可以降低程序发生崩溃的可能性,试想一下如果把所有功能都写到一个程序中,模块间的通信、异常处理将会很麻烦。

    主节点

    • 由于机器人的元器件很多,功能庞大,因此实际运行时往往会运行众多的node,负责感知世界、控制运动、决策和计算等功能。
    • 那么如何合理的进行调配、管理这些node?这就要利用ROS提供给我们的节点管master,master在整个网络通信架构里相当于管理中心,管理着各个node
    • node首先master处进行注册,之后master会将该node纳入整个ROS程序中
    • node之间的通信也是先由master进行“牵线”,才能两两的进行点对点通信
    • 当ROS程序启动时,第一步首先启动master,由节点管理器处理依次启动node

    节点和主节点之间的关系

    在这里插入图片描述

    基本命令

    roscore
    • 启动ros主节点,在运行ros程序之前都必须运行该命令启动主节点
    • 运行roscore时ROS master启动,同时启动的还有 rosout 和 parameter server ,
      • 其中rosout 是负责日志输出的一个节点,其作用是告知用户当前系统的状态,包括输出系统的error、warning等等,并且将log记录于日志文件中
      • parameter server 即是参数服务器,它并不是一个node,而是存储参数配置的一个服务器
    • 每一次我们运行ROS的节点前,都需要把master启动起来,这样才能够让节点启动和注册
    rosrun
    • 运行某一节点
    • 用法:rosrun [--prefix cmd] [--debug] pkg_name node_name [ARGS]
    • rosrun将会寻找PACKAGE下的名为EXECUTABLE的可执行程序,将可选参数ARGS传入
    • 例如在GDB下运行ros程序:rosrun --prefix 'gdb -ex run --args' pkg_name node_name
    rosnode
    # 列出当前运行的node信息
    rosnode list
    # 显示出node的详细信息
    rosnode info node_name
    # 结束某个node
    rosnode kill node_name
    # 测试连接节点
    rosnode ping
    # 列出在特定机器或列表机器上运行的节点
    rosnode machine
    # 清除不可到达节点的注册信息
    rosnode cleanup
    # 查看rosnode命令的用法
    rosnode help
    

    编写和运行ROS节点

    编写节点

    # 在home目录下运行以下命令创建一个名字为ros_workspace的工作空间
    $ mkdir –p ros_workspace/src
    # 切换到工作工件目录
    $ cd ros_workspace
    # 编译工作空间
    $ catkin_make
    # 设置环境变量
    $ echo “source ~/ros_workspace/devel/setup.bash” >> ~/.bashrc
    $ source ~/.bashrc
    
    # 切换到/src目录,创建一个test_pkg的功能包
    $ catkin_create_pkg test_pkg std_msgs rospy roscpp
    
    注意:

    ROS 包的命名遵循一个命名规范只允许使用小写字母、数字和下划线,而且首字符必须是一个小写字母。一些 ROS工具,包括 catkin,不支持那些不遵循此命名规范的包
    在这里插入图片描述

    ROS node头文件
    • 头文件
    • 头文件类型有gencpp模块根据msg定义自动生成
    • std_msgs/String.h
    • 使用rosmsg 查看具体内容
      在这里插入图片描述
    ROS node 基本结构
    • ros::init():初始化
    • ros::Publisher:发布消息
    • ros::Subscriber:订阅消息
    • ros::Rate loop_rate:循环速率
    • ros::spin():事件循环
    • ros::spinOnce():单次事件
    • ros::start():启动
    • ros::shutdown():关闭

    ros::init()
    • 通过调用ros::init()函数来初始化node
    • 此函数向ROS系统传递命令行参数定义node名字其它参数
    • 在调用roscpp其它函数前必须先调用ros::init(),其函数原型为:
      在这里插入图片描述
    ros::Publisher

    将节点设置成发布者,并将所发布主题的类型和名称告知节点管理器

    ros::Subscriber

    将节点设置成接收者,并将所接收主题的类型和名称告知节点管理器

    主循环
    • 循环条件 ros::ok(): 当接受到ctrl+c 信号 或者 ros::shutdown() 调用时,为false,终止运行节点
    • 主循环中,使用ros::rate 实现将循环一次的时间控制在一个我们设置的一个周期内
    • ROS_INFO();

    操作小记

    操作内容

    Hello World

    • 节点:
      • 节点talker:包含一个发布者
    • 节点间的通讯:
      • Topic(话题的名称):“chatter”
      • Message(传递的数据类型):std_msgs::String
        • String为 ROS自定义的数据类型
        • String中包含唯一变量为 std::string data
    编写节点测试代码

    在这里插入图片描述

    编译软件包

    我们主要需要修改CMakeLists.txt这个编译配置文件
    在这里插入图片描述

    编译

    当修改完CMakeLists.txt文件后 就可以在工作空间的根目录下使用catkin_make进行编译了
    在这里插入图片描述

    运行节点

    当编译过程没有错误时,接下来就可以使用rosrun命令来启动节点了
    在这里插入图片描述

    如何添加头文件和库文件

    如何引用自定义头文件

    引用当前软件包内的头文件

    在编写代码时我们经常会需要引用头文件,引用公用的头文件很容易,因为它们已经在标准库头文件路径中。但 如果要引用自定义的头文件就稍微麻烦点,我们首先查看软件包的目录结构,需要在正确的目录下创建头文件修改CMakeLists.txt文件这样才能正确编译,下面来举例说明:
    在这里插入图片描述
    在test_pkg.h内写入以下内容
    在这里插入图片描述
    修改源码文件,引用自定义头文件
    在这里插入图片描述
    修改CMakeLists.txt文件
    在这里插入图片描述
    运行效果
    在这里插入图片描述


    引用同一工作空间中其他软件包的头文件

    在一些情况我们需要引用其他软件包中提供的函数或宏定义,这样可以一定程度上减少我们在两个节点之间需要进行通信的话题个数,下面我们通过举例来进行说明:
    创建一个功能包
    在这里插入图片描述
    新建相关文件及文件夹
    在这里插入图片描述
    修改源码文件
    在这里插入图片描述
    修改两个软件包的编译配置文件
    在这里插入图片描述
    运行效果
    在这里插入图片描述

    如何引用第三方库文件

    我们经常在开发软件包时需要引入第三方的so动态库,但是将其放到系统默认库路径中或者使用绝对路径比较简单省事。但是这样的话我们软件包的移植性就会变差,当需要移植到其他机器上时需要重新配置该软件包的 依赖库路径

    手工自己创建测试用的动态库

    我们创建一个简单的动态库,里面只有一个简单的函数来计算两个输入整数的乘积并返回,我们首先创建multiply.cpp和multiply.h两个文件
    multiply.cpp
    在这里插入图片描述
    multiply.h
    在这里插入图片描述
    接下来准备开始将multiply.cpp编译成为动态库libmultiply.so供我们测试用,注意-shared参数和-fPIC参数很重要

    • -shared:告诉gcc要生成的是动态链接库;
    • -fPIC:告诉gcc生成的代码是非位置依赖的,方便用于动态链接。

    在这里插入图片描述

    将编译好的动态库复制到当前软件包对应的目录下
    在这里插入图片描述

    编辑代码和配置文件来引用动态库
    在这里插入图片描述

    修改编译配置文件,编译后运行效果演示
    在这里插入图片描述

    展开全文
  • fei33423 Merkle Tree 注意比特币的 tree , spv 简单支付证明,先通过服务端找到交易的块. 即证明了.Merkle Tree概念Merkle Tree,通常也被称作...非叶节点是其对应子节点串联字符串的hash。[1] phil 注: 这张图,有...

    fei33423 Merkle Tree 

    注意比特币的 tree , spv 简单支付证明,先通过服务端找到交易的块. 即证明了.

    Merkle Tree概念

    这里写图片描述

    Merkle Tree,通常也被称作Hash Tree,顾名思义,就是存储hash值的一棵树。Merkle树的叶子是数据块(例如,文件或者文件的集合)的hash值。非叶节点是其对应子节点串联字符串的hash。[1]

     phil 注: 这张图,有误导作用.节点不一定是2^n 次方.

    1、Hash

    Hash是一个把任意长度的数据映射成固定长度数据的函数[2]。例如,对于数据完整性校验,最简单的方法是对整个数据做Hash运算得到固定长度的Hash值,然后把得到的Hash值公布在网上,这样用户下载到数据之后,对数据再次进行Hash运算,比较运算结果和网上公布的Hash值进行比较,如果两个Hash值相等,说明下载的数据没有损坏。可以这样做是因为输入数据的稍微改变就会引起Hash运算结果的面目全非,而且根据Hash值反推原始输入数据的特征是困难的。[3]
      这里写图片描述
    如果从一个稳定的服务器进行下载,采用单一Hash是可取的。但如果数据源不稳定,一旦数据损坏,就需要重新下载,这种下载的效率是很低的。

    2、Hash List
    在点对点网络中作数据传输的时候,会同时从多个机器上下载数据,而且很多机器可以认为是不稳定或者不可信的。为了校验数据的完整性,更好的办法是把大的文件分割成小的数据块(例如,把分割成2K为单位的数据块)。这样的好处是,如果小块数据在传输过程中损坏了,那么只要重新下载这一快数据就行了,不用重新下载整个文件。

    怎么确定小的数据块没有损坏哪?只需要为每个数据块做Hash。BT下载的时候,在下载到真正数据之前,我们会先下载一个Hash列表。那么问题又来了,怎么确定这个Hash列表本事是正确的哪?答案是把每个小块数据的Hash值拼到一起,然后对这个长字符串在作一次Hash运算,这样就得到Hash列表的根Hash(Top Hash or Root Hash)。下载数据的时候,首先从可信的数据源得到正确的根Hash,就可以用它来校验Hash列表了,然后通过校验后的Hash列表校验数据块。
    这里写图片描述

    3、 Merkle Tree

    Merkle Tree可以看做Hash List的泛化(Hash List可以看作一种特殊的Merkle Tree,即树高为2的多叉Merkle Tree)。

    在最底层,和哈希列表一样,我们把数据分成小的数据块,有相应地哈希和它对应。但是往上走,并不是直接去运算根哈希,而是把相邻的两个哈希合并成一个字符串,然后运算这个字符串的哈希,这样每两个哈希就结婚生子,得到了一个”子哈希“。如果最底层的哈希总数是单数,那到最后必然出现一个单身哈希,这种情况就直接对它进行哈希运算,所以也能得到它的子哈希。于是往上推,依然是一样的方式,可以得到数目更少的新一级哈希,最终必然形成一棵倒挂的树,到了树根的这个位置,这一代就剩下一个根哈希了,我们把它叫做 Merkle Root[3]。

    在p2p网络下载网络之前,先从可信的源获得文件的Merkle Tree树根。一旦获得了树根,就可以从其他从不可信的源获取Merkle tree。通过可信的树根来检查接受到的Merkle Tree。如果Merkle Tree是损坏的或者虚假的,就从其他源获得另一个Merkle Tree,直到获得一个与可信树根匹配的Merkle Tree。

    Merkle Tree和Hash List的主要区别是,可以直接下载并立即验证Merkle Tree的一个分支。因为可以将文件切分成小的数据块,这样如果有一块数据损坏,仅仅重新下载这个数据块就行了。如果文件非常大,那么Merkle tree和Hash list都很到,但是Merkle tree可以一次下载一个分支,然后立即验证这个分支,如果分支验证通过,就可以下载数据了。而Hash list只有下载整个hash list才能验证。
      这里写图片描述

    Merkle Tree的特点

    1. MT是一种树,大多数是二叉树,也可以多叉树,无论是几叉树,它都具有树结构的所有特点; phil 注: 注意不是二叉排序树
    2. Merkle Tree的叶子节点的value是数据集合的单元数据或者单元数据HASH。
    3. 非叶子节点的value是根据它下面所有的叶子节点值,然后按照Hash算法计算而得出的。[4][5]
        

    通常,加密的hash方法像SHA-2和MD5用来做hash。但如果仅仅防止数据不是蓄意的损坏或篡改,可以改用一些安全性低但效率高的校验和算法,如CRC。

    Second Preimage Attack: Merkle tree的树根并不表示树的深度,这可能会导致second-preimage attack,即攻击者创建一个具有相同Merkle树根的虚假文档。一个简单的解决方法在Certificate Transparency中定义:当计算叶节点的hash时,在hash数据前加0x00。当计算内部节点是,在前面加0x01。另外一些实现限制hash tree的根,通过在hash值前面加深度前缀。因此,前缀每一步会减少,只有当到达叶子时前缀依然为正,提取的hash链才被定义为有效。

    Merkle Tree的操作

    1、创建Merckle Tree

      加入最底层有9个数据块。

      step1:(红色线)对数据块做hash运算,Node0i = hash(Data0i), i=1,2,…,9

      step2: (橙色线)相邻两个hash块串联,然后做hash运算,Node1((i+1)/2) = hash(Node0i+Node0(i+1)), i=1,3,5,7;对于i=9, Node1((i+1)/2) = hash(Node0i)

      step3: (黄色线)重复step2

      step4:(绿色线)重复step2

      step5:(蓝色线)重复step2,生成Merkle Tree Root
    这里写图片描述
    易得,创建Merkle Tree是O(n)复杂度(这里指O(n)次hash运算),n是数据块的大小。得到Merkle Tree的树高是log(n)+1。

    2、检索数据块

    为了更好理解,我们假设有A和B两台机器,A需要与B相同目录下有8个文件,文件分别是f1 f2 f3 ….f8。这个时候我们就可以通过Merkle Tree来进行快速比较。假设我们在文件创建的时候每个机器都构建了一个Merkle Tree。具体如下图:
    这里写图片描述
    从上图可得知,叶子节点node7的value = hash(f1),是f1文件的HASH;而其父亲节点node3的value = hash(v7, v8),也就是其子节点node7 node8的值得HASH。就是这样表示一个层级运算关系。root节点的value其实是所有叶子节点的value的唯一特征。

      假如A上的文件5与B上的不一样。我们怎么通过两个机器的merkle treee信息找到不相同的文件? 这个比较检索过程如下:

      Step1. 首先比较v0是否相同,如果不同,检索其孩子node1和node2.

      Step2. v1 相同,v2不同。检索node2的孩子node5 node6;

      Step3. v5不同,v6相同,检索比较node5的孩子node 11 和node 12

      Step4. v11不同,v12相同。node 11为叶子节点,获取其目录信息。

      Step5. 检索比较完毕。

      以上过程的理论复杂度是Log(N)。过程描述图如下:

    这里写图片描述
    从上图可以得知真个过程可以很快的找到对应的不相同的文件。

    3、更新,插入和删除

      虽然网上有很多关于Merkle Tree的资料,但大部分没有涉及Merkle Tree的更新、插入和删除操作,讨论Merkle Tree的检索和遍历的比较多。我也是非常困惑,一种树结构的操作肯定不仅包括查找,也包括更新、插入和删除的啊。后来查到stackexchange上的一个问题,才稍微有点明白,原文见[6]。

      对于Merkle Tree数据块的更新操作其实是很简单的,更新完数据块,然后接着更新其到树根路径上的Hash值就可以了,这样不会改变Merkle Tree的结构。但是,插入和删除操作肯定会改变Merkle Tree的结构,如下图,一种插入操作是这样的:
    这里写图片描述
    插入数据块0后(考虑数据块的位置),Merkle Tree的结构是这样的:
    这里写图片描述
    而[6]中的同学在考虑一种插入的算法,满足下面条件:
    - re-hashing操作的次数控制在log(n)以内
    - 数据块的校验在log(n)+1以内
    - 除非原始树的n是偶数,插入数据后的树没有孤儿,并且如果有孤儿,那么孤儿是最后一个数据块
    - 数据块的顺序保持一致
    - 插入后的Merkle Tree保持平衡

    然后上面的插入结果就会变成这样:
    这里写图片描述
    根据[6]中回答者所说,Merkle Tree的插入和删除操作其实是一个工程上的问题,不同问题会有不同的插入方法。如果要确保树是平衡的或者是树高是log(n)的,可以用任何的标准的平衡二叉树的模式,如AVL树,红黑树,伸展树,2-3树等。这些平衡二叉树的更新模式可以在O(lgn)时间内完成插入操作,并且能保证树高是O(lgn)的。那么很容易可以看出更新所有的Merkle Hash可以在O((lgn)2)时间内完成(对于每个节点如要更新从它到树根O(lgn)个节点,而为了满足树高的要求需要更新O(lgn)个节点)。如果仔细分析的话,更新所有的hash实际上可以在O(lgn)时间内完成,因为要改变的所有节点都是相关联的,即他们要不是都在从某个叶节点到树根的一条路径上,或者这种情况相近。

    [6]的回答者说实际上Merkle Tree的结构(是否平衡,树高限制多少)在大多数应用中并不重要,而且保持数据块的顺序也在大多数应用中也不需要。因此,可以根据具体应用的情况,设计自己的插入和删除操作。一个通用的Merkle Tree插入删除操作是没有意义的。


    展开全文
  • 单元测试

    千次阅读 2017-10-07 22:00:41
    单元测试 1,自动化测试 1.1通过断言的方式来确定结果是否正确Assert 1.2引入junit的jar包 建议直接使用eclipse中提供的包 1.3创建一个操作类 src目录下编写服务器代码 1,导入junit的jar,建议直接使用...
    单元测试
       1,自动化测试
           1.1通过断言的方式来确定结果是否正确Assert
           1.2引入junit的jar包 不建议直接使用eclipse中提供的包
           1.3创建一个操作类 在src目录下编写服务器代码
               1,导入junit的jar,不建议直接使用eclipse中所提供的包
               2,在src目录下编写服务代码
               3.创建测试类
               基本原则 1.在eclipse中创建一个source folder命名为test
                   2,创建一个测试类所在的包,包的名称和要测试的类一致
               4.Junit3和Junit4两者之间区别是非常明显的
               在Junit3中,如果某个类需要是测试类,必须将其继承与TestCase,如果某个方法需要是测试方法,必须让这个方法
               范通过textxx开头,在Junit3中,如果希望指定某个测试方法运行某个初始方法,这个方法名称必须setUp,如
               果希望在某个测试方法运行之后运行某个释放资源的方法,这个方法名称必须testDown
            在Junit4中,一个POJO类就是一个测试类,测试方法通过@Test来标识,初始化方法通过@Before,释放资源的方法通过 @After来
            标注,但是为了让Junit4中的类在Junit3中可以使用,习惯把初始化方法命名为setUp ,释放资源的方法命名为testDown 测试方法同样以test开头
            5, 如果使用断言
            
            hamcrest可以有效增加junit的测试能力,用一些相对通俗的语言来进行测试
            要使用junit中的assertThat来进行断言
            第一个参数表示实际值,第二个参数表示hamcrest的表达式
            
            特别注意,如果使用junit4.10 必须把hamcrest的jar包移到junit的jar之前,否则,组合条件allOf, anyOf都会抛出异常
            
            TestSuite
            可以通过testSuite来组成多个测试组件
            
            正常的开发流程
            编码---》测试-》重复--》提交
            基于测试驱动的开发
            测试-》编写-->重复---》提交
            先写了测试之后,由于测试的覆盖率要求为100%,所以就会让代码中可能存在的分支都进行测试,这样先写测试单元,
            可以为将来的代码提供了一种有效的参考
            
            cobertura使用
            1,将cobertura的路径设置到path中
            2,将要测试的源代码,编译之后的字节码文件和所需要的jar包拷贝到一个单独的目录中做处理
            3,在命令提示符中使用命令为生成测试覆盖报告的代码生成一个ser的文件
            3.1
             cobertura-instrument --destination instrumented  com/test/junit/     
            
            4.基于ser文件运行测试
            4.1java -cp lib/junit-4.10.jar;lib/cobertura.jar;.;instrumented;.;-Dnet.sourceforge.cobertura.datafile=cobertura.ser org.junit.runner.JUnitCore org.konghao.manager.TestUsertManager

            5.根据ser文件生成测试覆盖率的报告
            特别注意:如果文件的编码是utf-8的,在生成报告前需要为coberture-report.bat文件增加DfileEncoding的处理
            
            java -cp "%COBERTURA_HOME%cobertura.jar;%COBERTURA_HOME%lib\asm-3.0.jar;%COBERTURA_HOME%lib\asm-tree-3.0.jar;%COBERTURA_HOME%lib\log4j-1.2.9.jar;%COBERTURA_HOME%lib\jakarta-oro-2.0.8.jar" net.sourceforge.cobertura.reporting.Main %CMD_LINE_ARGS%
            
            
            黑盒测试
            
            白盒测试
            
       2,基于测试开发的方式和优点
       
       3,stub和mock
           mock对象用来测试一些未实现关联对象的类进行测试的对象
           mock和stub的区别
               mock关注的是交互
               stub关注的是状态
               EasyMock就是实现mock对象的框架
                   1,导入easymock的jar包    
                   2,Mock对象的三个生命周期
                       三个阶段 record  replay verify
                       Mock的关注点是在交互上,注意解决的问题是对象之间的交互,诸如:Service就依赖于DAO,如果DAO没有实现,我们可以通过Mock来模拟DAO的实现
                record阶段就是用来说明这个DAO上面可能存在的值
                
                @Test
        public void testLoad(){
            //1,创建DAO的Mock对象,目前就进入record阶段
            IUserDao ud= EasyMock.createMock(IUserDao.class);
            User u = new User(1,"admin","123","管理员");
            //2,记录ud可能会发生的操作的结果
            /*
             * 以下代码所指的是,当在dao中调用了load方法并且参数为admin的时候,返回值是u对象
             */
            //必须把交互的所有过程记录下来
            EasyMock.expect(ud.load("asd")).andReturn(u);
            ud.delete("abc");
            //以下用来操作没有返回值的方法
            EasyMock.expectLastCall();
            EasyMock.expect(ud.load("admin")).andReturn(u);
            //3进入测试阶段,也就是replay阶段
            EasyMock.replay(ud);
            //创建Service和DAO的关联
            IUserService us = new UserService(ud);
            //完成测试
            User tu = us.load("admin");
            EntitiesHelper.assertUser(tu,u);
            //3,验证交互关系是否正确
            EasyMock.verify(ud);
            
        }
        mock的几种创建方式,
        1,createMock
        通过createMock所创建的mock对象,在进行verify的时候仅仅只是检查关联方法是否正确完成调用,如果完成次数一致
        就认为测试通过,不考虑顺序问题
          public void testLoadMock(){
            //创建DAO的对象,目前就进入record阶段
            IUserDao ud = EasyMock.createMock(IUserDao.class);
            User u = new User(1,"admin","123","管理员");
            EasyMock.expect(ud.load("asd")).andReturn(u);
            //使用的CreateMock,如果方法的调用顺不一致,不会抛出异常
            ud.delete("abc");
            EasyMock.expectLastCall();
            EasyMock.expect(ud.load("admin")).andReturn(u);
            EasyMock.replay(ud);
            //创建Service和Dao关联
            IUserService us = new UserService(ud);
            //完成测试
            User tu = us.load("admin");
            EntitiesHelper.assertUser(tu,u);
            //验证交互关系是否正确
            EasyMock.verify(ud);
        }
        2,createSrtictMock
        在verify时不仅仅验证关联方法的调用此时还要验证顺序
        public void testLoadStrictMock(){
            //创建DAO的Mock对象,目前就进去了record阶段
            IUserDao ud = EasyMock.createStrictMock(IUserDao.class);
            User u = new User(1,"admin","123","管理员");
            EasyMock.expect(ud.load("asd")).andReturn(u);
            //使用的CreateStrictMock,方法的顺序不一致,所以会抛出异常
            ud.delete("abc");
            EasyMock.expectLastCall();
            EasyMock.expect(ud.load("admin")).andReturn(u);
            EasyMock.replay(ud);
            //关系serviceDao
            IUserService us = new UserService(ud);
            //完成测试
            User tu = us.load("admin");
            EntitiesHelper.assertUser(tu,u);
            //3,验证交互关系是否正确
            EasyMock.verify(ud);
        }
                                   
       4,在容器中测试
         4.1,jetty
         4.2 cactus 可以完成模拟J2EE的容器测试
                 可以测试servlet jsp filter 和EJB
         cactus注意是基于junit3.8来进行操作的,并不支持junit4中的annotaion
              搭建环境
              导入包 aspectjrt-1.5.3.jar  
              cactus.core.framework.uberjar.javaEE.14-1.8.1.jar
              cactus.integration.ant-1.8.1.jar
              cactus.integration.shared.api-1.8.1.jar
              commons-discovery-0.4.jar
              commons-httpclient-3.1.jar
              commons-logging-1.1.jar
              geronimo-j2ee-management_1.0_spec-1.1.jar
            httpunit-1.6.jar
            servlet-api-2.4.jar
            org.mortbay.jetty-5.1.9.jar
            commons-codec-1.7.jar
            cargo-core-uberjar-1.0-beta-2.jar
            cargo-core-container-jonas-1.0-beta-2.jar
            创建servlet的测试类
       5.dbUnit
           dbunit具体隔离数据库的访问,
             1导入jar包
               dbunit.jar
               slf4j.jar(一定使用1.6的版本)
             2,创建dbunit的测试数据xml文件
             <?xml version="1.0" encoding="UTF-8"?>
                <dataset>
                    <!--  <t_user>
                        <id>1</id>
                        <username>kh</username>
                        <password>123</password>
                        <nickname>孔浩</nickname>
                    </t_user>-->
                    <t_user id="1" username="admin" password="123" nickname="超级管理员"></t_user>
                </dataset>
             3,创建dbunit的Connection
             dbunit的connection是用来对数据文件进行操作的,这个connection必须依赖于目前项目中所使用的connection
            IDatabaseConnection com = new DatabaseConnection(DbUtil.getConnection());         
         4.创建IDdataSet,通过DATASET来获取测试数据
                     /**
                 * FlatXmlDataSet 用来获取基于属性存储的属性值
                 * XMLDateSet用来获取基于节点类型存储的属性值
                 */
                IDataSet ds = new FlatXmlDataSet(
                        new FlatXmlProducer(
                        new InputSource(
                        TestDbUnit.class.getClassLoader().getResourceAsStream("t_user.xml"))));
         
         5.初始化数据并且完成测试
                 //从DAO中获取数据并且完成测试
                IUserDao ud = new UserDao();
                User tu = ud.load("admin");
                assertEquals(tu.getId(), 1);
                assertEquals(tu.getUsername(), "admin");
                assertEquals(tu.getPassword(), "123");
                assertEquals(tu.getNickname(), "超级管理员");
                
         6. 备份
         
         @Test
        public void testBackup(){
            //超级dbunit的Connection 需要插入一个数据的connection作为参数
            try {
                DatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
                //根据con创建相应的dataset,这个dataset包含了所有表
                IDataSet ds = con.createDataSet();
                //将ds中的数据通过FlatXmlDataSet的格式写到文件中
                FlatXmlDataSet.write(ds, new FileWriter("D:/android_app/junit/junit01/test.xml"));
            } catch (DatabaseUnitException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        以上演示的是备份数据库的所有文件
        
        备份某些特定的表
        
        @Test
        public void testBackUpTable(){
            try {
                //创建dbunit的Connection ,需要传入一个数据库的connection作为参数
                IDatabaseConnection con = new DatabaseConnection(DbUtil.getConnection());
                //通过QueryDataSet可以有效的选择要处理的表来作为数据集
                QueryDataSet backup = new QueryDataSet(con);
                //添加t_user这张表作为备份表
                backup.addTable("t_user");
                FlatXmlDataSet.write(backup, new FileWriter("D:/android_app/junit/junit01/test1.xml"));
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (DatabaseUnitException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
       
    展开全文
  • 单元测试和Mock方法

    千次阅读 2016-10-26 21:21:12
    单元测试和MockService标签(空格分隔): 协作开发 虚拟接口 Android单元测试首先是开发的一部分,目的是保证没有耦合的情况下任何输入都能保证正确的输出(包括异常),可以保证程序的健壮性,避免代码腐烂化。...

    单元测试和MockService

    标签(空格分隔): 协作开发 虚拟接口 Android


    单元测试首先是开发的一部分,目的是保证没有耦合的情况下任何输入都能保证正确的输出(包括异常),可以保证程序的健壮性,避免代码腐烂化。其重要性是不言而喻的。查找了一些在Java中的测试思想以及测试工具,整理一下思路。

    在单元测试时,测试人员根据详细设计说明书和源程序清单,了解到该模块的I/O条件和模块的逻辑结构,主要采用白盒测试的测试用例,辅之以黑盒测试的测试用例,使之对任何合理和不合理的输入都要能鉴别和响应。这就要求对程序所有的局部和全局的数据结构、外部接口和程序代码的关键部分进行桌面检查和代码审查。


    测试内容

    边界条件

    在开发过程中,代码都是建立在正常的边界之内,对于边界与边界外的条件测试相对较少。边界条件是测试的重点之一,也是极易引发异常的重灾区。
    1. 一致性:值是否与预期一致
    2. 有序性:值是否像我们期望的那样有序或者无序
    3. 区间性:值是否位于合理的最大值和最小值之间
    4. 依赖性:代码是否引用了一些不在代码本省控制范围之内的外部资源(SD卡)等
    5. 存在性:值(对象)是否存在
    6. 基数性:是否恰好有足够的值(测试方法能否正确的计数)
    7. 时间性:所有的事件的发生是否是有序的,是否在正确的时刻返回正确或合理的值。

    局部数据结构测试

    1. 不正确或不一致的数据类型说明
    2. 使用尚未赋值或尚未初始化的变量
    3. 错误的初始值或错误的默认值
    4. 变量名拼写错或书写错
    5. 使用了外部变量或函数
    6. 不一致的数据类型
    7. 全局数据对模块的影响
    8. 数组越界
    9. 非法引用

    覆盖路径测试

    由于在测试时不可能做到穷举测试,所以在单元测试时要根据“白盒”测试和“黑盒”测试用例
    设计方法设计测试用例,对模块中重要的执行路径进行测试。重要的执行路径指那些处在完
    单元功能的算法、控制、数据处理等重要位置的执行路径,也指由于控制较复杂而易错的路径,有选择地对执行路径进行测试是一项重要的任务。应当设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误,对基本执行路径和循环进行测试可发现大量的路径错误。

    覆盖路径测试需要注意

    1. 死代码(dead code)执行不到的代码
    2. 算法错误
    3. 混用不同类的操作(泛型)
    4. 初始化不正确
    5. 精度错误—— 比较运算错误、赋值错误,表达式的不正确符号
    6. 循环变量的使用错误—— 错误赋值以及其他错误

    路径的测试是伴随着选择而来的,而选择在于条件的比较,大部分错误在于比较

    不同数据类型的比较。
    不正确的逻辑运算符或优先次序。
    因浮点运算精度问题而造成的两值比较不等。
    关系表达式中不正确的变量和比较符。
    “差 1 错”,即不正常的或不存在的循环中的条件。
    当遇到发散的循环时无法跳出循环。
    当遇到发散的迭代时不能终止循环。
    错误的修改循环变量。

    异常处理测试

    出错的描述是否难以理解,是否能够对错误定位
    显示的错误与实际的错误是否相符
    对错误条件的处理正确与否
    在对错误进行处理之前,错误条件是否已经引起系统的干预

    模块接口测试

    当完成内部测试之后,我们可以着手于对外部对接的测试。

    模块输入参数的数目是否与模块形式参数数目相同。
    模块各输入的参数属性与对应的形参属性是否一致。
    模块各输入的参数类型与对应的形参类型是否一致。
    传到被调用模块的实参的数目是否与被调用模块形参的数目相同。
    传到被调用模块的实参的属性是否与被调用模块形参的属性相同。
    传到被调用模块的实参的类型是否与被调用模块形参的类型相同。
    引用内部函数时,实参的次序和数目是否正确。
    是否引用了与当前入口无关的参数。
    用于输入的变量有没有改变。
    在经过不同模块时,全局变量的定义是否一致。
    限制条件是否以形参的形式传递。
    使用外部资源时,是否检查可用性并及时释放资源,如内存、文件、硬盘、端口等

    当模块进行外部设备输入/输出操作时,要测试以下额外项目

    文件的属性是否正确。
    Open与Close语句是否正确。
    规定的格式是否与I/O语句相符。
    缓冲区的大小与记录的大小是否相配合。
    在使用文件前,文件是否打开。
    文件结束的条件是否安排好了。
    I/O错误是否检查并做了处理。
    在输出信息中是否有文字错误。


    Mock对象

    维基百科上这样描述Mock:In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A computer programmer typically creates a mock object to test the behavior of some other object, in much the same way that a car designer uses a crash test dummy to simulate the dynamic behavior. of a human in vehicle impacts.
    Mock通常是指,在测试一个对象A时,我们构造一些假的对象来模拟与A之间的交互,而这些Mock对象的行为是我们事先设定且符合预期。通过这些Mock对象来测试A在正常逻辑,异常逻辑或压力情况下工作是否正常。
    引入Mock最大的优势在于:Mock的行为固定,它确保当你访问该Mock的某个方法时总是能够获得一个没有任何逻辑的直接就返回的预期结果。

    正常的过程
    1. MobileApi开发人员事先和App开发人员定义好MobileApi的接口(名称,参数,返回值)
    2. MobileApi按照约定写Mock接口,部署到测试环境,Mock Api中返回硬代码(JSON)数据。
    3. App开发人员基于上述测试环境的Mock接口,进行开发
    4. MobileApi开发完成后,通知App开发人员,对真实逻辑进行联调

    以上四步,如果正常实施,是没有问题的,但是问题经常出现在第二步。MobileApi无法及时提供Mock接口

    另外一种情况是:项目的进展需要更新现有接口字段,这是一个很耗时的过程

    解除依赖

    造成上面窘境的原因是模块与模块之间的依赖。我们可以在自己的App端设计自己的MockService,这样就可以完成步骤一之后,在APP端Mock自己的数据,直到开发完成,而不会被任何人阻塞,App开发完成后,如果有新的需要,可以请MobileApi开发人员汇总在一起修改。

    设计App端的MockService需要注意一下几点

    1, 对需要Mock的数据的MockApi接口,可以通过url.xml中配置Node节点MockClass属性,来指定要使用那个Mock子类生成的数据:

        <Node 
            Key="getWeatherInfo"
            Expires="300"
            NetType="get"
            MockClass="com.pirate.brook.mock.MockWeatherInfo"
            Url="http://www.weather.com.cn/xxx"/>

    2, 使用反射工厂来设计MockService。MockService是基类,它有一个抽象方法getJsonData,用于返回不同的Json数据,上述Node节点配置的MockWeatherInfo.class如下

    public class MockWeatherService extends MockService{
        @Override
        public String getJsonData() {
            WeatherInfo weatherInfo = new WeatherInfo(); // 实体编程
            weatherInfo.setCity("Beijing");
            weatherInfo.setCityId("10000");
    
            Response response = getSuccessResponse();
            response.setResult(JSON.toJSONSting(weatherInfo));
            return JSON.toJSONString(response); // 返回封装为完整的Response
        }
    }

    3,如何实现反射机制(RemoteService)

    public void invoke(final BaseActivity activity, 
                final String apiKey,
                final List<RequestParameter> params, 
                final RequestCallback callBack) {
            // 从xml文件中获取URLData
            final URLData urlData = UrlConfigManager.findURL(activity, apiKey);
            // 判断是否需要Mock
            if (urlData.getMockClass() != null) {
                try {
                    // 反射得到类的对象
                    MockService mockService = (MockService) Class.forName(
                            urlData.getMockClass()).newInstance();
                    String strResponse = mockService.getJsonData();
    
                    final Response responseInJson = JSON.parseObject(strResponse,
                            Response.class);
                    if (callBack != null) {
                        if (responseInJson.hasError()) {
                            callBack.onFail(responseInJson.getErrorMessage());
                        } else {
                            callBack.onSuccess(responseInJson.getResult());
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } else {
                HttpRequest request = activity.getRequestManager().createRequest(
                        urlData, params, callBack);
                DefaultThreadPool.getInstance().execute(request);
            }
        }

    URLData.class

    public class URLData {
        private String key;
        private long expires;
        private String netType;
        private String url;
        private String mockClass;
        }

    这样就减少了对各个模块的依赖


    另外一种解除依赖的方法—-使用Mockito库

    大家可以参考这篇入门文章Mockito简明教程

    展开全文
  • 人工神经网络有两个重要的超参数,用于控制网络的体系结构或拓扑:层数和每个隐藏层中的节点数。配置网络时,必须指定这些参数...这篇文章中,你将了解层和节点的作用,以及如何着手为你的预测建模问题配置多层感...
  • 软件测试_单元测试和集成测试

    千次阅读 2019-11-25 19:39:27
    title: 软件测试_单元测试和集成测试 date: 2019-11-25 15:58:23 categories: 软件测试 tags: 单元测试和集成测试 什么是单元测试 ...在单元工作过程中,其内部数据能够保持完整性。 可接收正确...
  • 使用GATT承载层时需要将蓝牙mesh协议数据单元(PDU)封装代理协议(Proxy Protocol)中,我们将下文中对此进行详细介绍。   节点与特性 成为蓝牙mesh网络中一员的设备被称为节点(Node) 。很多种...
  • 二叉树(根节点到任意结点的路径)

    千次阅读 热门讨论 2020-04-28 21:22:42
    其中,root指向二叉树的根结点,node指向二叉树中的另一结点,s 为已经初始化好的栈,该栈用来保存函数所计算的路径,如正确找出路径,则函数返回 true,此时root栈底,node栈顶;如未找到,则函数返回 false, ...
  • 上一次介绍了界面和一个简单的自由落体,然而实际运用中,机器人的结构都是可以大做文章的,天马星空的想象如果能仿真中运行一下是再好不过了的。这一次说一说webots下建模。    本人是学机械的,都知道...
  • 确定渲染树种所有节点的几何属性,比如:位置、大小等等,最后输入一个盒子模型,它能精准地捕获到每个元素屏幕内的准确位置与大小。 然后遍历渲染树,调用渲染器的 paint() 方法屏幕上显示其内容。 6.5. 合并...
  • 一、dits和fsimage   首先要提到两个文件edits和fsimage...当名称节点(NameNode)启动时,会从镜像文件 fsimage 中读取HDFS的状态,并且把edits文件中记录的操作应用到fsimage,也就是合并到fsimage中去。合并后
  • 单元测试中测试用例的设计方法

    千次阅读 2018-12-13 15:26:16
    1. 用于语句覆盖的基路径法 基路径法保证设计出的测试用例...控制流图是描述程序控制流的一种图示方法,主要由结点和边构成,边代表控制流的方向,节点代表控制流的汇聚处,边和结点圈定的空间叫做区域,下面是控...
  • Laxcus是Laxcus大数据实验室全体系自主设计研发的多用户多集群大数据管理系统,支持一到百万台级节点,提供零至EB量级数据存储、计算能力,集运行、开发、部署、维护为一体的平台。现在已经多地部署和投入运营。逐...
  • LSTM单元

    千次阅读 2017-07-12 09:57:56
    本文译自 Christopher Olah 的博文 ...你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考
  • MSP432输入输出模块

    千次阅读 2019-06-30 19:47:10
    单片机中的输入输出模块是供信号输入、输出所用的模块化单元。MsP432单片机的片内输入输出模块非常丰富,典型的输入输出模块有:通用O端口、模/数转换模块、比较器E  定时器。本章重点讲述MSP432单片机的各个典型...
  • 正确认识C语言当代的地位和作用

    万次阅读 2012-04-25 15:03:00
    无意中网上看到了06年的一些关于C语言还是否值得大部分的程序员去学习的争论。中间涉及到了大量的C语言与C++、C#的一些对比, 现整理出来, 方便大家查看。也是自己做个笔记。 为什么每个程序员都应该学习...
  • 布局与绘制 确定渲染树种所有节点的几何属性,比如:位置、大小等等,最后输入一个盒子模型,它能精准地捕获到每个元素屏幕内的准确位置与大小。 然后遍历渲染树,调用渲染器的 paint() 方法屏幕上显示其内容。...
  • 本文按照自己的理解从硬件磁盘到文件系统的逐层网上的思路开展,从操作系统的角度详解Linux文件系统层次、文件系统分类、文件系统的存储结构、不同存储介质的区别(RAM、ROM、Flash)、存储节点inode。
  • • 对于控制器上下文的每个节点,都会此界面中生成常量 (WDCTX_),并将该节点的名称(大写字母)作为该常量的值。 该常量用于访问上下文节点。 可由标准属性WD_CONTEXT 访问上下文根节点。可使用get
  • 软件测试是软件开发阶段中的一个重要环节,良好的测试方法是保证软件质量的根基。软件测试根据软件开发阶段按过程划分为:1.单元测试 2.集成测试 3.确认测试 4....现在有一些常用的单元测试框架:1.JUnit
  • ANSYS——如何选择合适的单元类型

    千次阅读 2020-05-26 11:11:27
    1.该选杆单元(Link)还是梁单元(Beam)? 2.对于薄壁结构,是选实体单元还是壳单元? 3.实体单元的选择 一、单元1)link(杆)系列: (2)beam(梁)系列: (3)shell(板壳)系列 (4)solid(体)系列 (5)...
  • 一句话的警告:我将本文中谈论单元测试和测试驱动开发(TDD),如果你已经得出结论:下面的任何理由对你都适合,那么请继续阅读,或者至少阅读从我为什么要关心?到最后:  我使用一个库,如jQuery,它保
  • ANSYS经典界面中梁单元实例全解析

    千次阅读 2020-05-24 17:03:49
    转载的文章中提到的梁单元截面是常用的工字形,那么要是规则的截面形状的话需要自己进行截面形状绘制,具体可以参考这篇文章:https://blog.csdn.net/qq_45769063/article/details/106316667 目录 导读: 一、...
  • 软件测试系列之单元测试 (转载)

    千次阅读 2010-09-20 18:42:00
    vs2005如何使用cppunit 1. 编译cppunit目前vs2005下直接编译cppunit工程是编译过去的。还要对cppunit工程做一下适当的改动才能成功编译。虽然网上有些文章介绍使用CPPUnitProjectWizard。但是我查阅了相关...
  • Cpus节点需要特别的特性,但是通常习惯指定#address-cells = <1>和#size-cells = ,这指定了各个CPU节点的reg属性的格式,其用于编码物理CPU号。 CPU节点的格式为cpu@x,model属性描述CPU类型,其他的是时钟频率...
  • gtest单元测试

    千次阅读 2011-11-15 18:54:12
    此贴是是从整理过来的,自己看的方便。...我会工作中,对自己的使用感受和用法,对文章进行不断的修改 ================================我是华丽的分割线================================ 使用体会
  • 作者最近复习考博,乘此机会分享一些计算机科学与技术、软件工程等相关专业课程考题,一方面分享给考研、考博、找工作的博友,另一方面也是自己今后完成这些课程的复习资料,同时也是在线笔记。基础知识,希望对您...
  • 第一次听到这个词还是Blacksburg的公寓,王俊鹏向我介绍了计算机研究领域的几大方向,其中就有机器学习,人工智能。给我举得例子就是语义识别,不断给计算机喂书,然后拿出来一本计算机从来没有见过的书,计算机便...
  • (可再看)深度学习学习笔记(1

    千次阅读 2016-07-29 14:19:36
    一、概述 ...是的,人类和大量现成数据的帮助下,电脑可以表现的十分强大,但是离开了这两者,它甚至都能分辨一个喵星人和一个汪星人。 图灵(图灵,大家都知道吧。计算机和人工智能的鼻祖,分别

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,516
精华内容 19,006
关键字:

在单元1输入的节点不正确