【问题标题】:Test two different npm package versions at the same time同时测试两个不同的 npm 包版本
【发布时间】:2018-05-05 17:21:24
【问题描述】:

当我创建一个 npm 包时,有时它会面临需要回退旧的依赖包版本。

如果新版本有新的api,我可以这样写代码:

import pkg from 'some-pkg';
const isNewVersion = pkg.newVersionApi !== 'undefined';

if (isNewversion) {
  pkg.newVersionApi();
} else {
  pkg.oldVersionApi(); // backward compatible api
}

并且使用这种模式,当我想编写测试时,我只能测试installed version 代码。其他版本的代码无法测试。

例如,在 React v15 和 v16 中,React v16 有新的 API Portal。在 Portal 发布之前,v15 有unstable_renderSubtreeIntoContainer api 来实现类似的功能。

所以 React 的代码应该是这样的:

import ReactDOM from 'react-dom';
const isV16 = ReactDOM.createPortal !== 'undefined';

if (isV16) {
  ReactDOM.createPortal(...);
} else {
  ReactDOM.unstable_renderSubtreeIntoContainer(...);
}

所以我想问有没有什么方法可以用different dependency version进行测试?

目前,我想到的一种方法是再次安装另一个版本并进行测试。但它只能在本地进行。它不能在 ci 上工作,也不能一起计入覆盖范围。

我认为这不仅适用于反应测试。它可能面临 node.js 测试。任何建议都可以讨论。

更新

这个问题可能与在 npm 中安装 two versions dependency 有关。但我知道目前安装两个版本的依赖是不可行的。

【问题讨论】:

  • K.I.S.S.原则:这里最快(也是技术最少)的解决方案是使用您的应用程序的两个单独副本,每个副本都有您要测试的不同包版本。这对于git 来说是微不足道的,因为您可以 1) 克隆您的应用两次或 2) 使用两个单独的分支。
  • 没错。使用单独的分支是一种方法。但如果这是一个开源项目或合作项目。很难控制合并分支问题。因为我们需要告诉贡献者遵循测试路线图,例如在两个分支上更新您的更改并对其进行测试。

标签: javascript node.js reactjs testing npm


【解决方案1】:

除了其他建议之外,您还可以尝试Testing multiple versions of a module dependency 中描述的方法。

下面是使用这种方法测试多个webpack 版本的示例:

npm install --save-dev module-alias
npm install --save-dev webpack-v4@npm:webpack@4.46.0
npm install --save-dev webpack-v5@npm:webpack@5.45.1

module-alias package 处理包版本之间切换的魔力,同时仍支持正常的require('webpack')(或任何您的模块)调用。

另一个installs 将创建两个版本的依赖项,每个版本在您的本地node_modules/ 中都有一个不同的目录名称。

然后,在您的测试代码中,您可以通过以下方式设置依赖别名:

const path = require('path');
require('module-alias').addAlias(
  'webpack',
  path.resolve('node_modules', 'webpack-v4'),
);

// require('webpack') will now pull in webpack-v4

您会在不同的测试工具中为 'webpack-v5' 做同样的事情。

如果您的任何子依赖项在其自己的代码中的任何位置都有硬编码的require('webpack'),这将确保它们也提取正确的webpack 版本。

【讨论】:

    【解决方案2】:

    这是一个可能的解决方案,不确定它是否会按您的预期工作。但是,你会有前进的方向。

    package.json

    {
      "name": "express-demo",
      "version": "0.0.0",
      "private": true,
      "scripts": {
        "start": "node ./bin/www"
      },
      "dependencies": {
        "cookie-parser": "~1.4.3",
        "debug": "~2.6.3",
        "express": "~4.15.2",
        "jade": "~1.11.0",
        "morgan": "~1.8.1",
        "serve-favicon": "~2.4.2",
        "webpack": "^3.8.1",
        "webpack-dev-middleware": "^1.12.0",
        "webpack-hot-middleware": "^2.20.0"
      },
      "customDependecies": {
        "body-parser": [
          "",
          "1.18.1",
          "1.18.0"
        ]
      }
    }
    

    注意在上面的package.json 文件中,我添加了一个新密钥customDependecies,我将使用它来安装多个依赖项。这里我使用body-parser 包进行演示。接下来你需要文件,它可以读取这个key 并安装deps。

    安装-deps.js

    const {spawnSync} = require('child_process');
    const fs = require('fs');
    
    const customDependencies = require('./package.json').customDependecies;
    
    spawnSync('mkdir', ['./node_modules/.tmp']);
    
    for (var dependency in customDependencies) {
      customDependencies[dependency].forEach((version) => {
        console.log(`Installing ${dependency}@${version}`);
        if (version) {
          spawnSync('npm', ['install', `${dependency}@${version}`]);
          spawnSync('mv', [`./node_modules/${dependency}`, `./node_modules/.tmp/${dependency}@${version}`]);
        } else {
          spawnSync('npm', ['install', `${dependency}`]);
          spawnSync('mv', [`./node_modules/${dependency}`, `./node_modules/.tmp/${dependency}`]);
        }
      });
    
      customDependencies[dependency].forEach((version) => {
        console.log(`Moving ${dependency}@${version}`);
        if (version) {
          spawnSync('mv', [`./node_modules/.tmp/${dependency}@${version}`, `./node_modules/${dependency}@${version}`]);
        } else {
          spawnSync('mv', [`./node_modules/.tmp/${dependency}`, `./node_modules/${dependency}`]);
        }
      });
    }
    spawnSync('rm', ['-rf', './node_modules/.tmp']);
    console.log(`Installing Deps finished.`);
    

    在这里,我在tmp 文件夹中一一安装deps,安装后,我将它们移动到./node_modules 文件夹中。

    一切都安装好后,您可以查看以下版本

    index.js

    var bodyParser = require('body-parser/package.json');
    var bodyParser1181 = require('body-parser@1.18.1/package.json');
    var bodyParser1182 = require('body-parser@1.18.0/package.json');
    
    console.log(bodyParser.version);
    console.log(bodyParser1181.version);
    console.log(bodyParser1182.version);
    

    希望,这将达到您的目的。

    【讨论】:

    • 酷!解决测试问题似乎更优雅。你有什么想法可以一起计算覆盖率吗?
    • 我不确定,“一起计算覆盖率”是什么意思?
    • 因为测试覆盖率是基于一个测试进程计算的,当我使用这种方式构建项目时,我需要在每个不同的版本上运行测试进程,覆盖率不能整合在一起(例如:v1测试 + v2 测试...)。
    • 您能否解释一下您认为可以在您的代码中使用的格式。我从来没有做过测试覆盖:(
    • 请注意那些使用范围包的人:您需要将mv 命令更改为:mv ./node_modules/.tmp/${scope}/${dependency}@${version} ./node_modules/${dependency}@${version}
    【解决方案3】:

    您将不得不单独运行它们。为每个依赖版本创建一个单独的项目文件夹。前任。反应10,反应11,反应12。每个都有自己的package.json,为正确的版本指定。当您运行 integration 和/或 versioned 测试时,您将在每个版本中运行标准单元测试,但也建议将任何特定于版本的单元测试添加到该文件夹​​。

    创建一个make 文件将使您在运行完整的测试套件时更轻松。如果您这样做,您可以轻松地将其集成到 CI 中。

    【讨论】:

    • 这是一种可行的解决方案。但是因为只是 api 变化有点不同,我可能会在不同的版本中复制一些代码。此外,它不能一起计算代码覆盖率。
    • 你要复制什么代码?您应该在每个版本中运行相同的单元测试。为每个版本添加额外测试的想法是在不再支持某个版本时更容易删除它们,并允许您测试仅在该版本上出现的内容。
    【解决方案4】:

    创建 3 个单独的项目(带有 package.json 的文件夹)和一个共享文件夹:

    1. 包含测试模块的共享文件夹 (my-test)。导出一个函数来运行测试;
    2. 导入my-test 和依赖v1 的客户端项目。导出调用my-test中的测试函数的函数。
    3. 导入my-test 和依赖v2 的客户端项目。导出调用my-test中的测试函数的函数。
    4. 导入两个客户端项目的主项目。运行每个导出的函数。

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 2017-09-13
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      相关资源
      最近更新 更多