如何使用Jasmine和Webpack运行Typescript(而不是AngularJs)单元测试

时间:2017-03-03 17:39:46

标签: unit-testing typescript webpack jasmine

有很多关于如何使用Webpack和Jasmine进行Angular项目单元测试的信息。

但我有一个项目使用'普通'打字稿,而不是AngularJs。所以我有ts类,但我不使用组件。 我无法弄清楚如何将我找到的信息应用于非AngularJs项目;一切似乎都是为了使用组件。

如何将Jasmine(ts spec文件)集成到Typescript Webpack项目中?

我更喜欢使用单独的webpack配置进行测试的解决方案。

我的设置/我必须使用的内容:

的package.json 启动脚本使用dev-build启动节点

{
  "name": "webpack.typescript",
  "version": "1.0.0",
  "description": "Webpack + TypeScript",
  "main": "dev-build.js",
  "author": "Shane Osbourne and John Lindquist",
  "license": "MIT",
  "scripts": {
    "start": "node dev-build"
  },
  "dependencies": {
    "bootstrap": "^3.3.7",
    "lodash": "^4.17.4"
  },
  "devDependencies": {
    "@types/lodash": "^4.14.53",
    "browser-sync": "^2.18.8",
    "bs-pretty-message": "^1.0.8",
    "css-loader": "^0.26.2",
    "node-sass": "^4.5.0",
    "sass-loader": "^6.0.2",
    "style-loader": "^0.13.2",
    "ts-loader": "^2.0.1",
    "typescript": "^2.2.1",
    "url-loader": "^0.5.8",
    "webpack": "^2.2.1",
    "webpack-dev-middleware": "^1.10.1"
  }
}

DEV-build.js 加载配置,捆绑并启动BrowserSync。

/**
 * Require Browsersync along with webpack and middleware for it
 */
var browserSync          = require('browser-sync').create();
var webpack              = require('webpack');
var webpackDevMiddleware = require('webpack-dev-middleware');

/**
 * Require ./dev-webpack.config.js and make a bundler from it
 */
var webpackConfig = require('./dev-webpack.config');
var bundler       = webpack(webpackConfig);

/**
 * Reload all devices when bundle is complete
 * or send a fullscreen error message to the browser instead
 */
bundler.plugin('done', function (stats) {
    if (stats.hasErrors() || stats.hasWarnings()) {
        return browserSync.sockets.emit('fullscreen:message', {
            title: "Error",
            timeout: 100000
        });
    }
    browserSync.reload();
});

/**
 * Run Browsersync and use middleware for Hot Module Replacement
 */
browserSync.init({
    server: 'app',
    open: false,
    logFileChanges: false,
    middleware: [
        webpackDevMiddleware(bundler, {
            publicPath: webpackConfig.output.publicPath,
            stats: {colors: true}
        })
    ],
    plugins: ['bs-pretty-message'],
    files: [
        'app/css/*.css',
        'app/*.html'
    ]
});

DEV-webpack.config.js 处理打字稿和scss。 (我以为我应该有一个test-webpack.config.js)

var webpack = require('webpack');
var path = require('path');

module.exports = {
  devtool: '#inline-source-map',

  entry: [
    './src/main.ts',
    './src/main.scss'
  ],

  output: {
    path: path.join(__dirname, 'app'),
    publicPath: '/',
    filename: 'dist/bundle.js'
  },

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.LoaderOptionsPlugin({
      debug: true
    })
  ],

  resolve: {
    extensions: ['.ts', '.js', '.scss']
  },

  module: {
    rules: [
      {
        test: /\.ts$/, use: [{
          loader: 'ts-loader'
        }]
      },
      {
        test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
        use: [{
          loader: 'url-loader'
        }]
      },
      {
        test: /\.scss$/,
        use: [{
          loader: "style-loader"
        }, {
          loader: "css-loader", options: {
            sourceMap: true
          }
        }, {
          loader: "sass-loader", options: {
            sourceMap: true
          }
        }]
      }
    ],
  }
};

我发现了什么:

https://dzone.com/articles/unit-testing-with-webpack-amp-mocha

Unit testing with Webpack, Jasmine (-core), typescript

Jasmine Spec as Typescript File

TypeScript compilation failure and Karma test execution?

Executing Typescript Jasmine tests via Webpack (Terminal) to test Angular2

2 个答案:

答案 0 :(得分:5)

Ngz的答案仍然包括角度和许多额外的东西。 所以我会尽力回答这些必需品。

test-webpack-config.js将测试作为入口点,因为webpack从那里查找依赖项,而ts-loader进行转换:

var webpack = require('webpack');
var path = require('path');

module.exports = {
  devtool: '#inline-source-map',

  entry: [
    './test/index.spec.ts',
  ],

  output: {
    filename: 'dist/bundle.js'
  },

  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.LoaderOptionsPlugin({
      debug: true
    })
  ],

  resolve: {
    extensions: ['.ts', '.js', '.tsx']
  },

  module: {
    rules: [
      {
        test: /\.ts$/, use: [{
          loader: 'ts-loader'
        }]
      }]
  }
};

我使用karma作为测试运行器,使用karma-webpack插件,这里是配置:

var webpackConfig = require('./test-webpack.config.js');

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],


    // list of files / patterns to load in the browser
    files: [
      'test/*.spec.ts',
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
       'test/**/*.spec.ts': ['webpack'],
       'src/**/*.ts': ['webpack'],
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity, 

    mime: {
      'text/x-typescript': ['ts','tsx']
    },

    // Set Webpack configuration, but set the entry to spec files
    webpack: {
      module: webpackConfig.module,
      resolve: webpackConfig.resolve
    }
  })
}

mime部分是使用打字稿进行测试的关键。

完整示例:https://github.com/SierraNL/webpack-typescript-jasmine

答案 1 :(得分:4)

您需要设置一个测试运行器并将其配置为使用稍微不同的Webpack配置进行测试。对于这个例子,我使用了Karma和karma-webpack插件。

您需要为测试包创建一个单独的条目文件,并在您的karma配置文件的filespreprocessors属性值中引用它:

// /test/karma.conf.js
const argv = require('yargs').argv;
const isDebug = argv.debug === 'true';
const isCoverage = argv.coverage === 'true';
const path = require('path');
const webpack = require('webpack');

// Optional instrumentation loader for coverage reporting
const instrumentLoader = {
    test: /\.js$|\.ts$/,
    enforce: 'post',
    use: [
        {
            loader: 'istanbul-instrumenter-loader',
            options: {
                esModules: true
            }
        }
    ],
    exclude: /node_modules/
};

const coverageReporter = {
    reporters: [
        {
            type: 'text-summary'
        }
    ]
}

module.exports = (config) => {
    config.set(Object.assign({
            browsers: [isDebug ? 'Chrome' : 'PhantomJS'],
            files: [
                // test bundle entry file
                './test.entry.js'
            ],
            frameworks: ['jasmine', 'es6-shim'],
            reporters: isDebug ? ['spec'] : ['spec', 'coverage'],
            singleRun: !isDebug,
            autoWatch: isDebug,
            preprocessors: {
                // test bundle entry file
                './test.entry.js': ['webpack']
            },
            webpackMiddleware: {
                stats: 'errors-only'
            }
        },
        (isCoverage ? { coverageReporter } : {}),
        {
            webpack: {
                devtool: 'eval-source-map',
                resolve: {
                    extensions: [
                        '.js',
                        '.ts',
                        '.less',
                        '.html',
                        '.json'
                    ],
                    modules: [path.resolve(process.cwd(), 'src/client'), 'node_modules']
                },
                module: {
                    rules: [
                        {
                            test: /\.js$/,
                            use: [
                                'babel-loader'
                            ],
                            exclude: /node_modules/
                        },
                        {
                            test: /\.ts$/,
                            use: [
                                'babel-loader',
                                {
                                    loader:'ts-loader',
                                    options: {
                                        entryFileIsJs: true
                                    }
                                }
                            ],
                            exclude: /node_modules/
                        }
                    ].concat(isCoverage ? [instrumentLoader] : [])
                }
            }
        }
    ));
};

然后创建测试包入口点:

// /test/test.entry.js
// Add polyfills/vendor libs for your tests
import 'babel-core/register';
import 'babel-polyfill';

// Build a context of files matching our pattern
const context = require.context('./', true, /^\.\/.*\.spec\.(js|ts)$/);

// Require all of the files in the context
context.keys().forEach(context);

然后,您可以使用karma.conf.js的路径以及--debug--coverage的参数调用Karma:

$ karma start ./test/karma.conf.js --coverage=true --debug=false

或者更好的是,将它放入package.json scripts属性:

// package.json
{
    ...
    "scripts": {
        "test": "cross-env karma ./test/karma.conf.js",
        "test:watch": "cross-env karma ./test/karma.conf.js --debug=true",
        "test:coverage": "cross-env karma ./test/karma.conf.js --coverage=true",
    }
    ...
}

使用npm:npm run test

调用