首页 文章

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

提问于
浏览
9

关于如何使用Webpack和Jasmine进行Angular项目单元测试有大量信息 .

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

How do I integrate Jasmine (ts spec files) in a Typescript Webpack project?

我更喜欢使用单独的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 回答

  • 4

    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

  • 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

相关问题