当前位置:首页 > EDA > 电子设计自动化
[导读]受限嵌入式Java做单测,核心不是把JUnit全套搬进板子,而是“业务算法离板跑、硬件访问靠抽象、板端只跑冒烟”。GPIO、ADC、串口、Modbus驱动不直连测试类,统一成HardwarePort接口,主机用Fake/Mock造数据,ARM小内存设备只跑精简用例。


受限嵌入式Java做单测,核心不是把JUnit全套搬进板子,而是“业务算法离板跑、硬件访问靠抽象、板端只跑冒烟”。GPIO、ADC、串口、Modbus驱动不直连测试类,统一成HardwarePort接口,主机用Fake/Mock造数据,ARM小内存设备只跑精简用例。

一、硬件抽象与桩件设计

先定义端口接口,把所有寄存器、文件节点、JNI调用关在里面:

public interface HardwarePort {

   int readRaw(int channel);

   void writeRaw(int channel, int value);

   long lastUpdated(int channel);

}

测试用Fake实现,可人为制造超量程、超时、固定值:

public class FakeHardwarePort implements HardwarePort {

   private final int[] values;

   private long ts = System.currentTimeMillis();

   public FakeHardwarePort(int[] values) { this.values = values; }

   public int readRaw(int ch) { return values[ch]; }

   public void writeRaw(int ch, int v) { values[ch] = v; }

   public long lastUpdated(int ch) { return ts; }

}

真实设备用JNI/字符设备实现同一接口;单测不加载so、不碰/dev,避免板端资源争用和状态不可复现。

二、业务单测与断言

以ADC量程清洗为例,零漂、满量程、死区都在主机JUnit覆盖:

import org.junit.Test;

import static org.junit.Assert.*;

public class AdcCleanTest {

   @Test

   public void linearScaleOk() {

       HardwarePort hw = new FakeHardwarePort(new int[]{32768, 0, 65535});

       AdcService svc = new AdcService(hw, 0, 4.0, 20.0); // ch0,0~65535->4~20mA

       double v = svc.readEngineering(0);

       assertEquals(12.0, v, 0.01);

   }

   @Test

   public void outOfRangeMarkBad() {

       HardwarePort hw = new FakeHardwarePort(new int[]{70000});

       AdcService svc = new AdcService(hw, 0, 4.0, 20.0);

       assertTrue(Double.isNaN(svc.readEngineering(0)));

   }

}

AdcService只依赖HardwarePort,不依赖具体板子;协议解析、点表映射、班次聚合、离线补发都用同样方式做纯逻辑单测。Mockito/jMock仅用于复杂依赖,小内存项目尽量用Fake代替动态字节码Mock,减少启动开销。

三、受限板端冒烟测试

256MB~1GB网关可跑裁剪测试包,不跑全量回归。用JUnit ConsoleLauncher或自建main执行指定Suite:

public class BoardSmokeTest {

   public static void main(String[] args) {

       int fail = 0;

       HardwarePort hw = new JniHardwarePort();

       AdcService svc = new AdcService(hw, 0, 4.0, 20.0);

       double v = svc.readEngineering(0);

       if (v < 3.9 || v > 20.1) { System.out.println("ADC SMOKE FAIL"); fail++; }

       System.out.println(fail == 0 ? "SMOKE OK" : "SMOKE ERR:" + fail);

       System.exit(fail);

   }

}

JVM限小堆,避免测试期OOM:

java -Xms32m -Xmx96m -XX:+UseSerialGC \

 -cp test.jar:app.jar BoardSmokeTest

只验关键链路:硬件读值、协议转换、本地缓存、MQTT组包;重UI、重历史库放到主机CI。

四、离板CI与覆盖率

GitHub/GitLab Runner跑主机全量:src/test/java覆盖协议、清洗、告警、报表;硬件用Fake,串口/网络用回环或仿真服务。 Maven示例:

<plugin>

 <groupId>org.jacoco</groupId>

 <artifactId>jacoco-maven-plugin</artifactId>

 <version>0.8.11</version>

 <executions>

   <execution><goals>

     <goal>prepare-agent</goal>

   </goals></execution>

   <execution><id>report</id><phase>test</phase><goals>

     <goal>report</goal>

   </goals></execution>

 </executions>

</plugin>

JaCoCo动态插桩收集行/分支覆盖,受限设备用offline模式更省内存。 门禁建议核心清洗、协议解析分支覆盖≥90%,UI和驱动适配只做连通冒烟。

五、落地要点

所有时间、随机、文件、网络都走可注入接口,测试不依赖墙钟和真实网卡;

寄存器状态、告警阈值、Modbus异常码用Fake预置,保证用例可重复;

小内存板不用PowerMock/JMockit重装字节码,能用构造注入就用构造注入;

CI出HTML覆盖报告,板端OTA前跑冒烟jar,返回SMOKE OK再切生产;

硬件仿真缺件时,用JSON定义虚拟设备、容器跑回放,补PLC/传感器异常场景。

按“接口抽象+Fake桩+主机JUnit全量+板端小堆冒烟+JaCoCo轻量覆盖”搭建,既能在笔记本/CI秒级回归,又能在嵌入式网关低内存环境自动验关键链路,避免把重型测试框架硬塞进终端。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭