admin管理员组

文章数量:1330428

When I create an npm package, sometimes it would face the need to backward old dependency package version.

If the new version has new api, I may write the code in this pattern:

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

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

And with this pattern, when I want to write the test, I only can test the installed version code. The other version's code can't be tested.

For real example, in React v15 and v16, React v16 has new API Portal. Before Portal release, v15 has unstable_renderSubtreeIntoContainer api to realize similar feature.

So the code for React would be like:

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

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

So I want to ask is there any method to test with different dependency version?

Currently, one method I think of is to install the other version again and test it. But it only can do on local. It can't work on ci and it can't count in coverage together.

I think that is not only for react test. It may face on node.js test. Any suggestion can be discussed.

Updated

This question maybe is related to install two versions dependency in npm. But I know currently installing two versions dependency is not workable.

When I create an npm package, sometimes it would face the need to backward old dependency package version.

If the new version has new api, I may write the code in this pattern:

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

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

And with this pattern, when I want to write the test, I only can test the installed version code. The other version's code can't be tested.

For real example, in React v15 and v16, React v16 has new API Portal. Before Portal release, v15 has unstable_renderSubtreeIntoContainer api to realize similar feature.

So the code for React would be like:

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

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

So I want to ask is there any method to test with different dependency version?

Currently, one method I think of is to install the other version again and test it. But it only can do on local. It can't work on ci and it can't count in coverage together.

I think that is not only for react test. It may face on node.js test. Any suggestion can be discussed.

Updated

This question maybe is related to install two versions dependency in npm. But I know currently installing two versions dependency is not workable.

Share Improve this question edited Nov 28, 2017 at 18:25 Chen-Tai asked Nov 22, 2017 at 4:22 Chen-TaiChen-Tai 3,4733 gold badges24 silver badges34 bronze badges 2
  • K.I.S.S. Principle: The quickest (and least technical) solution here would be to use two separate copies of your app, each with the different package versions you'd want to test. This is trivial to do with git, since you can either 1) clone your app twice or 2) use two separate branches. – Denny Commented Nov 22, 2017 at 5:01
  • That's right. Using separate branch is one way. But if this is an open source or a co-working project. It's hard to control the merge branch problem. Because we need to tell the contributors to follow the test roadmap like update your change on both branch and test it. – Chen-Tai Commented Nov 22, 2017 at 5:09
Add a ment  | 

4 Answers 4

Reset to default 5 +50

Here is a might be solution, not sure it will work as you expect. But, you will have a direction to move forward.

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"
    ]
  }
}

Note in above package.json file, I have added a new key customDependecies which I will use for installing multiple dependencies. Here I am using body-parser package for demo. Next you need file, that can read this key and install the deps.

install-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.`);

Here, I am installing deps one by one in tmp folder and once installed, I am moving them to ./node_modules folder.

Once, everything is installed, you can check the versions like below

index.js

var bodyParser = require('body-parser/package.json');
var bodyParser1181 = require('[email protected]/package.json');
var bodyParser1182 = require('[email protected]/package.json');

console.log(bodyParser.version);
console.log(bodyParser1181.version);
console.log(bodyParser1182.version);

Hope, this will serve your purpose.

Create 3 separate projects (folders with package.json) and a shared folder:

  1. A shared folder containing the test module (my-test). Export a function to run the test;
  2. A client project importing my-test and dependency v1. Export a function that calls the test function in my-test.
  3. A client project importing my-test and dependency v2. Export a function that calls the test function in my-test.
  4. A master project that imports both client projects. Run each exported function.

You're going to have to run them separately. Create a separate project folder for each dependency version. Ex. React10, React11, React12. Each will have its own package.json, specified for the correct version. When you run the integration and/or versioned tests, you'll run your standard unit tests across each version, but it may also be advisable to add any version specific unit tests to that folder.

Creating a make file would make your life easier when running your full testing suite. If you do this you can easily integrate this into CI.

In addition to the other suggestions, you can try the approach described at Testing multiple versions of a module dependency.

Here's an example of using this approach to test against multiple webpack versions:

npm install --save-dev module-alias
npm install --save-dev webpack-v4@npm:[email protected]
npm install --save-dev webpack-v5@npm:[email protected]

The module-alias package handles the magic of switching between package versions while still supporting normal require('webpack') (or whatever your module is) calls.

The other installs will create two versions of your dependency, each with a distinct directory name within your local node_modules/.

Then, within your test code, you can set up the dependency alias via:

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

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

You'd do the same thing for 'webpack-v5' in a different test harness.

If any of your sub-dependencies have a hardcoded require('webpack') anywhere in their own code, this will ensure that they also pull in the correct webpack version.

本文标签: javascriptTest two different npm package versions at the same timeStack Overflow