You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cypress中对比两个JSON文件并输出差异的实现方法

在Cypress中对比JSON文件:忽略属性顺序,仅检测缺失属性与值差异

在用Cypress编写测试用例对比两个JSON文件时,会遇到三类问题:部分属性缺失、属性顺序不一致、属性值存在差异。直接使用cy.readFile()配合deep.equal断言会因为属性顺序不同直接报错,无法获取完整的缺失/差异信息。需要实现自定义对比逻辑,忽略属性顺序,仅检测并打印缺失属性和值差异到控制台。

示例文件

file1.json(预期文件)

{
    "isActive": true,
    "isLocked": false,
    "phone": null,
    "details": [
      { 
       "firstName":"test1",
       "lastName": "last1",
       "userId": "testuser1",
       "lastLoggedIn": "2024-01-01"
      }
    ]
}

file2.json(实际文件)

{
    "isActive": true,
    "phone": "123-456-7890",
    "details": [
      { 
       "firstName":"test1",
       "userId": "testuser1",
       "lastLoggedIn": "2024-01-02"
      }
    ],
    "isLocked": false
}

期望控制台输出

+ expected - actual

-   "phone": "123-456-7890",
    "details": [
    { 
-    lastLoggedIn: "2024-01-02"
    }
   ]
--
+   "phone": null,     
    "details": [
    { 
+    lastName: "last1",
+    lastLoggedIn: "2024-01-01"
    }
   ]

解决方案

1. 编写自定义JSON对比函数

该函数递归遍历对象和数组,忽略属性顺序,收集三类差异:实际文件缺失的属性、实际文件多余的属性、属性值不一致的情况。

function compareJSON(expected, actual) {
  const diff = {
    missing: [], // actual中缺失的属性(expected有,actual无)
    extra: [], // actual中多出来的属性(expected无,actual有)
    mismatched: [] // 属性值不一致的情况
  };

  // 对比对象
  if (typeof expected === 'object' && expected !== null && typeof actual === 'object' && actual !== null) {
    const expectedKeys = Object.keys(expected).sort();
    const actualKeys = Object.keys(actual).sort();

    // 查找缺失属性
    expectedKeys.forEach(key => {
      if (!actualKeys.includes(key)) {
        diff.missing.push(`+ ${key}: ${JSON.stringify(expected[key])}`);
      } else {
        // 递归对比嵌套属性
        const nestedDiff = compareJSON(expected[key], actual[key]);
        if (nestedDiff.missing.length || nestedDiff.extra.length || nestedDiff.mismatched.length) {
          diff.mismatched.push(`- ${key}: ${JSON.stringify(actual[key])}`);
          diff.mismatched.push(`+ ${key}: ${JSON.stringify(expected[key])}`);
        }
      }
    });

    // 查找多余属性
    actualKeys.forEach(key => {
      if (!expectedKeys.includes(key)) {
        diff.extra.push(`- ${key}: ${JSON.stringify(actual[key])}`);
      }
    });
  } 
  // 对比数组(默认匹配对应位置元素,若需忽略顺序可额外修改排序逻辑)
  else if (Array.isArray(expected) && Array.isArray(actual)) {
    const maxLength = Math.max(expected.length, actual.length);
    for (let i = 0; i < maxLength; i++) {
      if (i >= actual.length) {
        diff.missing.push(`+ [${i}]: ${JSON.stringify(expected[i])}`);
      } else if (i >= expected.length) {
        diff.extra.push(`- [${i}]: ${JSON.stringify(actual[i])}`);
      } else {
        const nestedDiff = compareJSON(expected[i], actual[i]);
        if (nestedDiff.missing.length || nestedDiff.extra.length || nestedDiff.mismatched.length) {
          diff.mismatched.push(`- [${i}]: ${JSON.stringify(actual[i])}`);
          diff.mismatched.push(`+ [${i}]: ${JSON.stringify(expected[i])}`);
        }
      }
    }
  } 
  // 对比基本类型值
  else {
    if (expected !== actual) {
      diff.mismatched.push(`- ${JSON.stringify(actual)}`);
      diff.mismatched.push(`+ ${JSON.stringify(expected)}`);
    }
  }

  return diff;
}

2. 在Cypress测试用例中调用函数

读取两个JSON文件,执行对比逻辑,格式化输出差异到控制台:

cy.readFile('../src/cypress/fixtures/file1.json').then(expected => {
  cy.readFile('../src/cypress/fixtures/file2.json').then(actual => {
    const diff = compareJSON(expected, actual);
    
    // 格式化输出差异
    console.log('+ expected - actual\n');
    console.log('- actual differences:\n');
    if (diff.extra.length) console.log(diff.extra.join('\n'));
    const actualMismatches = diff.mismatched.filter(line => line.startsWith('-'));
    if (actualMismatches.length) console.log(actualMismatches.join('\n'));
    
    console.log('\n--\n');
    
    console.log('+ expected differences:\n');
    if (diff.missing.length) console.log(diff.missing.join('\n'));
    const expectedMismatches = diff.mismatched.filter(line => line.startsWith('+'));
    if (expectedMismatches.length) console.log(expectedMismatches.join('\n'));
    
    // 可选:若需测试失败,可根据差异是否存在断言
    if (diff.missing.length || diff.extra.length || diff.mismatched.length) {
      throw new Error('JSON文件存在差异');
    }
  });
});

内容的提问来源于stack exchange,提问作者S K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:25:30