分布式场景自动化测试框架设计与实现 原创

进修的泡芙
发布于 2025-6-17 21:22
浏览
0收藏

分布式场景自动化测试框架设计与实现

一、项目概述

基于HarmonyOS的分布式自动化测试框架,可模拟多设备协同场景并验证功能正确性。借鉴《鸿蒙跨端U同步》中的设备发现、状态同步和任务分发机制,实现跨设备测试场景的自动化执行与结果验证,确保分布式功能在不同设备组合下的可靠性。

二、架构设计

±--------------------+
测试编排引擎
(Test Orchestrator)

±---------±---------+
±---------v----------+ ±--------------------+

分布式任务调度 <—> 设备测试执行器
(Task Dispatcher) (Test Executor)

±---------±---------+ ±--------------------+
±---------v----------+

结果聚合与分析
(Result Analyzer)

±--------------------+

三、核心代码实现
测试编排引擎

// 测试编排服务
public class TestOrchestrator {
private static final String TAG = “TestOrchestrator”;
private DistributedTaskDispatcher dispatcher;
private TestResultCollector resultCollector;

public TestOrchestrator(Context context) {
    this.dispatcher = DistributedTaskDispatcher.getInstance(context);
    this.resultCollector = new TestResultCollector(context);

// 执行分布式测试场景

public void executeTestScenario(TestScenario scenario) {
    // 1. 设备发现与筛选
    List<DeviceInfo> matchedDevices = discoverDevices(scenario.getDeviceRequirements());
    
    // 2. 任务分发
    Map<String, TestTask> taskMap = createTaskMap(scenario, matchedDevices);
    dispatcher.dispatchTasks(taskMap);
    
    // 3. 结果收集与分析
    resultCollector.collectResults(taskMap.keySet(), new TestResultListener() {
        @Override
        public void onAllResultsCollected(Map<String, TestResult> results) {
            generateTestReport(scenario, matchedDevices, results);

});

// 设备发现与筛选

private List<DeviceInfo> discoverDevices(DeviceRequirements requirements) {
    List<DeviceInfo> allDevices = DeviceManager.getInstance().getAvailableDevices();
    List<DeviceInfo> matchedDevices = new ArrayList<>();
    
    for (DeviceInfo device : allDevices) {
        if (requirements.matches(device)) {
            matchedDevices.add(device);
            
            if (matchedDevices.size() >= requirements.getMaxDevices()) {
                break;

}

return matchedDevices;

// 创建任务映射

private Map<String, TestTask> createTaskMap(TestScenario scenario, 
    List<DeviceInfo> devices) {
    
    Map<String, TestTask> taskMap = new HashMap<>();
    List<TestAction> actions = scenario.getActions();
    
    for (int i = 0; i < devices.size(); i++) {
        DeviceInfo device = devices.get(i);
        TestTask task = new TestTask();
        task.setDeviceId(device.getDeviceId());
        
        // 分配设备角色和对应动作
        String role = scenario.getRoles().get(i % scenario.getRoles().size());
        task.setRole(role);
        
        List<TestAction> roleActions = new ArrayList<>();
        for (TestAction action : actions) {
            if (action.getTargetRole().equals(role)) {
                roleActions.add(action);

}

        task.setActions(roleActions);
        
        taskMap.put(device.getDeviceId(), task);

return taskMap;

// 生成测试报告

private void generateTestReport(TestScenario scenario, 
    List<DeviceInfo> devices, Map<String, TestResult> results) {
    
    TestReport report = new TestReport(scenario, devices, results);
    report.generateHtmlReport();
    
    // 保存或显示报告
    ReportViewer.showReport(report);

// 设备需求类

public static class DeviceRequirements {
    private List<DeviceType> deviceTypes;
    private int minDevices;
    private int maxDevices;
    
    public boolean matches(DeviceInfo device) {
        return deviceTypes.contains(device.getDeviceType());

// Getters & Setters

    public List<DeviceType> getDeviceTypes() { return deviceTypes; }
    public int getMinDevices() { return minDevices; }
    public int getMaxDevices() { return maxDevices; }

// 测试场景类

public static class TestScenario {
    private String name;
    private List<String> roles; // 设备角色列表
    private List<TestAction> actions;
    private DeviceRequirements deviceRequirements;
    
    // Getters
    public String getName() { return name; }
    public List<String> getRoles() { return roles; }
    public List<TestAction> getActions() { return actions; }
    public DeviceRequirements getDeviceRequirements() { return deviceRequirements; }

// 测试动作类

public static class TestAction {
    private String name;
    private String targetRole;
    private Map<String, Object> params;
    
    // Getters
    public String getName() { return name; }
    public String getTargetRole() { return targetRole; }
    public Map<String, Object> getParams() { return params; }

}

分布式任务调度服务

// 分布式任务调度服务
public class DistributedTaskDispatcher {
private static final String TASK_CHANNEL = “dist_test_task”;
private static final String RESULT_CHANNEL = “dist_test_result”;
private static DistributedTaskDispatcher instance;
private DistributedDataManager dataManager;

private DistributedTaskDispatcher(Context context) {
    this.dataManager = DistributedDataManagerFactory.getInstance()
        .createDistributedDataManager(context);

public static synchronized DistributedTaskDispatcher getInstance(Context context) {

    if (instance == null) {
        instance = new DistributedTaskDispatcher(context);

return instance;

// 分发测试任务

public void dispatchTasks(Map<String, TestTask> taskMap) {
    for (Map.Entry<String, TestTask> entry : taskMap.entrySet()) {
        String deviceId = entry.getKey();
        TestTask task = entry.getValue();
        
        dataManager.putString(
            TASK_CHANNEL + "_" + deviceId,
            GsonUtils.toJson(task)
        );

}

// 注册结果监听器
public void registerResultListener(String sessionId, TaskResultListener listener) {
    dataManager.registerDataChangeListener(
        RESULT_CHANNEL + "_" + sessionId,
        new DataChangeListener() {
            @Override
            public void onDataChanged(String deviceId, String key, String value) {
                TestResult result = GsonUtils.fromJson(value, TestResult.class);
                listener.onTaskResult(deviceId, result);

}

    );

// 测试任务类

public static class TestTask {
    private String deviceId;
    private String role;
    private List<TestAction> actions;
    
    // Getters & Setters
    public String getDeviceId() { return deviceId; }
    public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
    public String getRole() { return role; }
    public void setRole(String role) { this.role = role; }
    public List<TestAction> getActions() { return actions; }
    public void setActions(List<TestAction> actions) { this.actions = actions; }

public interface TaskResultListener {

    void onTaskResult(String deviceId, TestResult result);

}

测试执行器实现

// 测试执行Ability
public class TestExecutorAbility extends Ability {
private static final String TAG = “TestExecutor”;
private DistributedDataManager dataManager;
private TestTaskExecutor taskExecutor;

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    
    dataManager = DistributedDataManagerFactory.getInstance()
        .createDistributedDataManager(this);
    taskExecutor = new TestTaskExecutor(this);
    
    // 监听测试任务
    dataManager.registerDataChangeListener(
        TASK_CHANNEL + "_" + DeviceInfo.getLocalDeviceId(),
        new DataChangeListener() {
            @Override
            public void onDataChanged(String deviceId, String key, String value) {
                TestTask task = GsonUtils.fromJson(value, TestTask.class);
                executeTestTask(task);

}

    );

// 执行测试任务

private void executeTestTask(TestTask task) {
    new Thread(() -> {
        TestResult result = taskExecutor.execute(task);
        
        // 上报测试结果
        dataManager.putString(
            RESULT_CHANNEL + "_" + task.getSessionId(),
            GsonUtils.toJson(result)
        );
    }).start();

// 测试任务执行器

private class TestTaskExecutor {
    private Context context;
    
    public TestTaskExecutor(Context context) {
        this.context = context;

public TestResult execute(TestTask task) {

        TestResult result = new TestResult();
        result.setDeviceId(task.getDeviceId());
        result.setRole(task.getRole());
        
        for (TestAction action : task.getActions()) {
            ActionResult actionResult = executeAction(action);
            result.addActionResult(actionResult);

return result;

private ActionResult executeAction(TestAction action) {

        ActionResult result = new ActionResult();
        result.setActionName(action.getName());
        result.setStartTime(System.currentTimeMillis());
        
        try {
            // 根据动作类型执行不同的测试逻辑
            switch (action.getName()) {
                case "verifyDeviceDiscovery":
                    result.setSuccess(testDeviceDiscovery());
                    break;
                case "verifyDataSync":
                    result.setSuccess(testDataSync(action.getParams()));
                    break;
                case "verifyCrossDeviceCall":
                    result.setSuccess(testCrossDeviceCall(action.getParams()));
                    break;
                default:
                    result.setSuccess(false);
                    result.setErrorMessage("Unknown action: " + action.getName());

} catch (Exception e) {

            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());

result.setEndTime(System.currentTimeMillis());

        return result;

// 测试设备发现功能

    private boolean testDeviceDiscovery() {
        List<DeviceInfo> devices = DeviceManager.getInstance()
            .getAvailableDevices();
        return !devices.isEmpty();

// 测试数据同步功能

    private boolean testDataSync(Map<String, Object> params) {
        String testKey = "sync_test_" + System.currentTimeMillis();
        String testValue = params.get("testValue").toString();
        
        dataManager.putString(testKey, testValue);
        String receivedValue = dataManager.getString(testKey);
        
        return testValue.equals(receivedValue);

}

// 测试结果类
public static class TestResult {
    private String deviceId;
    private String role;
    private List<ActionResult> actionResults = new ArrayList<>();
    
    // Getters & Setters
    public String getDeviceId() { return deviceId; }
    public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
    public String getRole() { return role; }
    public void setRole(String role) { this.role = role; }
    public List<ActionResult> getActionResults() { return actionResults; }
    public void addActionResult(ActionResult result) { actionResults.add(result); }

// 动作结果类

public static class ActionResult {
    private String actionName;
    private long startTime;
    private long endTime;
    private boolean success;
    private String errorMessage;
    
    // Getters & Setters
    public String getActionName() { return actionName; }
    public void setActionName(String actionName) { this.actionName = actionName; }
    public long getStartTime() { return startTime; }
    public void setStartTime(long startTime) { this.startTime = startTime; }
    public long getEndTime() { return endTime; }
    public void setEndTime(long endTime) { this.endTime = endTime; }
    public boolean isSuccess() { return success; }
    public void setSuccess(boolean success) { this.success = success; }
    public String getErrorMessage() { return errorMessage; }
    public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }

}

结果收集与分析

// 测试结果收集器
public class TestResultCollector {
private static final String TAG = “TestResultCollector”;
private DistributedTaskDispatcher taskDispatcher;
private Map<String, TestResult> collectedResults = new ConcurrentHashMap<>();

public TestResultCollector(Context context) {
    this.taskDispatcher = DistributedTaskDispatcher.getInstance(context);

// 收集测试结果

public void collectResults(Set<String> deviceIds, TestResultListener listener) {
    String sessionId = "session_" + System.currentTimeMillis();
    
    taskDispatcher.registerResultListener(sessionId, new DistributedTaskDispatcher.TaskResultListener() {
        @Override
        public void onTaskResult(String deviceId, TestResult result) {
            collectedResults.put(deviceId, result);
            
            if (collectedResults.size() == deviceIds.size()) {
                listener.onAllResultsCollected(new HashMap<>(collectedResults));
                collectedResults.clear();

}

    });

// 测试报告生成器

public static class TestReportGenerator {
    public static String generateHtmlReport(TestScenario scenario, 
        List<DeviceInfo> devices, Map<String, TestResult> results) {
        
        StringBuilder html = new StringBuilder();
        html.append("<html><head><style>")
           .append("body { font-family: Arial, sans-serif; margin: 20px; }")
           .append("h1 { color: #333; }")
           .append("table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }")
           .append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }")
           .append("th { background-color: #f2f2f2; }")
           .append(".pass { background-color: #dff0d8; }")
           .append(".fail { background-color: #f2dede; }")
           .append("</style></head><body>")
           .append("<h1>分布式测试报告</h1>")
           .append("<h2>测试场景: ").append(scenario.getName()).append("</h2>");
        
        // 设备信息汇总
        html.append("<h3>测试设备</h3><table>")
           .append("<tr><th>设备ID</th><th>设备名称</th><th>设备类型</th><th>角色</th></tr>");
        
        for (DeviceInfo device : devices) {
            TestResult result = results.get(device.getDeviceId());
            html.append("<tr>")
               .append("<td>").append(device.getDeviceId()).append("</td>")
               .append("<td>").append(device.getDeviceName()).append("</td>")
               .append("<td>").append(device.getDeviceType()).append("</td>")
               .append("<td>").append(result.getRole()).append("</td>")
               .append("</tr>");

html.append(“</table>”);

        // 测试结果详情
        html.append("<h3>测试结果详情</h3><table>")
           .append("<tr><th>设备/动作</th>");
        
        // 动态生成动作表头
        Set<String> allActions = new HashSet<>();
        for (TestResult result : results.values()) {
            for (ActionResult actionResult : result.getActionResults()) {
                allActions.add(actionResult.getActionName());

}

        for (String action : allActions) {
            html.append("<th>").append(action).append("</th>");

html.append(“</tr>”);

        // 填充测试结果
        for (DeviceInfo device : devices) {
            TestResult result = results.get(device.getDeviceId());
            if (result == null) continue;
            
            html.append("<tr>")
               .append("<td>").append(device.getDeviceName()).append("</td>");
            
            for (String action : allActions) {
                boolean found = false;
                for (ActionResult actionResult : result.getActionResults()) {
                    if (action.equals(actionResult.getActionName())) {
                        html.append("<td class=\"")
                           .append(actionResult.isSuccess() ? "pass" : "fail")
                           .append("\">")
                           .append(actionResult.isSuccess() ? "✓" : "✗")
                           .append("</td>");
                        found = true;
                        break;

}

                if (!found) {
                    html.append("<td>-</td>");

}

            html.append("</tr>");

html.append(“</table></body></html>”);

        return html.toString();

}

public interface TestResultListener {
    void onAllResultsCollected(Map<String, TestResult> results);

}

四、XML布局示例

<!-- 测试控制台布局 test_console_layout.xml -->
<DirectionalLayout
xmlns:ohos=“http://schemas.huawei.com/res/ohos
ohos:width=“match_parent”
ohos:height=“match_parent”
ohos:orientation=“vertical”
ohos:padding=“24vp”>

<Text
    ohos:width="match_parent"
    ohos:height="wrap_content"
    ohos:text="分布式测试控制台"
    ohos:text_size="32fp"
    ohos:margin_bottom="24vp"/>
    
<ScrollView
    ohos:width="match_parent"
    ohos:height="0vp"
    ohos:weight="1">
    
    <ListContainer
        ohos:id="$+id/scenario_list"
        ohos:width="match_parent"
        ohos:height="match_content"/>
</ScrollView>

<Button
    ohos:id="$+id/execute_btn"
    ohos:width="match_parent"
    ohos:height="60vp"
    ohos:text="执行测试"
    ohos:margin_top="16vp"/>

</DirectionalLayout>

<!-- 测试报告布局 test_report_layout.xml -->
<DirectionalLayout
xmlns:ohos=“http://schemas.huawei.com/res/ohos
ohos:width=“match_parent”
ohos:height=“match_parent”
ohos:orientation=“vertical”>

<WebView
    ohos:id="$+id/report_webview"
    ohos:width="match_parent"
    ohos:height="match_parent"/>
    
<Button
    ohos:id="$+id/export_btn"
    ohos:width="match_parent"
    ohos:height="60vp"
    ohos:text="导出报告"
    ohos:margin="16vp"/>

</DirectionalLayout>

五、技术创新点
多设备场景编排:灵活定义设备角色和交互场景

自动化任务分发:根据设备能力自动分配测试任务

智能结果分析:自动聚合多设备测试结果并生成可视化报告

分布式同步机制:借鉴游戏同步技术确保测试步骤一致性

可扩展架构:支持快速添加新的测试场景和验证逻辑

六、总结

本分布式场景自动化测试框架实现了以下核心价值:
全面覆盖:验证分布式功能在各种设备组合下的表现

效率提升:自动化执行复杂的多设备交互场景

问题发现:快速定位分布式场景中的兼容性问题

质量保障:确保跨设备协同功能的可靠性

标准规范:建立统一的分布式功能测试方法

系统借鉴了《鸿蒙跨端U同步》中的设备协同机制,将游戏场景的同步技术应用于自动化测试领域。未来可结合AI技术实现智能场景生成和异常预测,并与CI/CD流程深度集成实现持续验证。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐