【问题标题】:How to create QUnit tests with reference to another class?如何参考另一个类创建 QUnit 测试?
【发布时间】:2015-08-19 21:39:06
【问题描述】:

我正在尝试将 JavaScript 单元测试添加到我的网站中。我用的是VS2013,我的项目是一个ASP.NET网站。

基于我迄今为止所做的建议 (http://www.rhyous.com/2013/02/20/creating-a-qunit-test-project-in-visual-studio-2010/):

  1. 创建了新的 ASP.NET 应用
  2. 导入的 QUnit(使用 NuGet)
  3. 在“脚本”中添加了指向我原始网站中 js 文件的链接(文件 PlayerSkill.js - 包含 PlayerSkill 类和 trainings.js - 包含 Trainer 和其他一些类)
  4. 创建了新文件夹“TestScripts”
  5. 添加了 TrainingTests.js 文件
  6. 写了简单的测试:

     test( "Trainer should have non-empty group", function () {
        var group = "group";
        var trainer = new Trainer(123, "Name123", group, 123);
        EQUAL(trainer.getTrainerGroup(), group);
     });
    

注意:我的 trainings.js 文件包括

function Trainer(id, name, group, level) {
    ... 
    var _group = group;
    this.getTrainerGroup = function () { return _group ; }
};

我在执行测试时看到错误:未定义培训师。

似乎无法识别对我的班级的引用。我觉得链接文件还不够,但我错过了什么?

请帮助添加对带有类的原始文件的引用并运行单元测试。

谢谢。

附:问题 2:我可以添加对 2 个文件的引用(我的单元测试将需要另一个文件中的一个类)吗?怎么样?

【问题讨论】:

  • 请说明您究竟是如何执行测试的。您可以打开浏览器和 html 页面,也可以使用命令行,这一点很重要。

标签: javascript visual-studio unit-testing qunit


【解决方案1】:

您应该将应用程序的所有相关逻辑添加到您的单元测试文件中,以便它们都在您运行测试之前执行

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>QUnit Test Results</title>
        <link rel="stylesheet" href="/Content/qunit.css">
    </head>
    <body>
        <div id="qunit"></div>
        <div id="qunit-fixture"></div>
        <script src="/Scripts/qunit.js"></script>
        <script src="/Scripts/PlayerSkill.js"></script>
        <script src="/Scripts/trainings.js"></script>
        <script src="/TestScripts/TrainingTests.js"></script>
    </body>
</html>

不应该使用链接文件,因为它们不会实际存在于脚本文件夹中。

如果你真的想使用它们,你应该让 Visual Studio intellisense 像这样解析文件的物理路径。

  1. 键入脚本标签&lt;script src=""&gt;&lt;/script&gt;
  2. 将光标放在 src 属性中的引号内,然后按CTRL + SPACE
  3. 搜索您的文件并保持解析的路径不变
  4. 如果您的项目位置发生变化,您必须更新链接文件以及脚本引用。

{编辑1}

解决方案 2:

您还可以使用 MVC 控制器和 Razor 视图来创建您的单元测试页面,并且链接的文件将按预期工作,唯一的问题是您的项目中将有一个额外的控制器,但这一点也不错,如果例如,您想使用 ajax 测试内容的加载,如果它们是从本地文件运行的,则默认情况下会被浏览器阻止。

解决方案 3:

您还可以为您的 javascript 单元测试设置一个新的 MVC 项目,就像您通常为任何服务器端代码设置一个新项目一样,这将有助于防止您的测试干扰您的生产代码

{编辑 2}

解决方案 4:

作为 javascript 生态系统的一部分,您可以使用 grunt 或 gulp 在运行测试之前自动将脚本从任何地方复制到项目中。你可以像这样写一个 gulpfile.js

var sourcefiles = [/*you project file paths*/];
gulp.task('default', function () {
    return gulp.src(sourcefiles).pipe(gulp.dest('Scripts'));
});

然后运行它打开控制台并运行命令gulpgulp default

【讨论】:

  • 关于评论的第一部分:在“”中点击 Ctrl+Space 没有帮助:VS 不允许从当前网站中选择文件。
  • 关于第二部分:你建议在我的原始项目中创建 MVC 控制器和 Razor View 吗?我显然想避免这种情况。但是如果我在测试项目中创建它们......那将如何解决问题?我仍然无法引用外部文件。您是否建议动态加载外部 JS 文件?
  • @Budda 关于第一部分VS 如果您将文件添加为链接,则解析路径,否则您尚未添加它。我已经测试过并且正在工作。关于第二部分,人们通常为单元测试创​​建单独的项目,因此您可以为 javascript 创建一个单独的 MVC 项目,这取决于项目的大小和单元测试的数量。恕我直言,正确的方法是在测试之前创建一个 gulp 任务并复制您的脚本文件,但这对于非常简单的项目来说可能很复杂。
  • 是的,我确实创建了一个单独的项目,但是没有复制带有要测试的类的JS文件。不知道为什么,也许我犯了一些愚蠢的错误,但是添加链接真的很简单,所以我想知道我怎么会做错事。无论如何,谢谢你的帮助。第一次听说gulp,现在很抱歉我没有接受你的回答,你只得到了一半的奖金
  • @Budda 这里的诀窍是您创建一个单独的 MVC 项目并在脚本文件夹中添加所有 .js 文件,但不是添加标准方式(制作副本),而是将其添加为链接。这样做的原因是,当您使用 razor(不要使用 html 文件)构建 QUnit 测试页面时,因此当 VS 找到链接文件时,它会在任何位置搜索真实文件并始终从可预测的位置提供它,即&lt;script src="~/scripts/training.js"&gt;&lt;/script&gt;
【解决方案2】:

看起来trainings.js 在调用TrainingTests.js 时没有定义。请参阅this 问题以获取有关为什么会发生这种情况的更多详细信息!一旦解决了它就可以工作。是的,类似于trainings.js,只要您正确引用它们,您就可以在任何文件夹中拥有任意数量的文件。我创建了一个可访问的示例小提琴@http://plnkr.co/edit/PnqVebOzmPpGu7x2qWLs?p=preview

<body>
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <script src="http://code.jquery.com/qunit/qunit-1.18.0.js"></script>
  <script src="trainings.js"></script>
  <script src="TrainingTests.js"></script>
</body>

【讨论】:

  • 谢谢,但我确实想参考文件。尝试从另一个网站引用一个网站的 JS 不起作用。我相信 VS 和 IIS 只是阻止了这种情况。
  • 好的,但你的问题没有提到需要从另一台服务器引用 js 文件:)
【解决方案3】:

好吧,由于两个答案的帮助,我确实本地化了这个问题,确实是 VS 无法将所需的文件复制到测试项目中。

这可能可以通过多种方式解决,我找到了一种,想法复制自:http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml

解决方法很简单:动态添加标签

为了实现这一点,我在标签中添加了以下代码:

<script>
    var fileref = document.createElement('script');
    fileref.setAttribute("type", "text/javascript");
    var path = 'path'; // here is an absolute address to JS-file on my web site
    fileref.setAttribute("src", path);
    document.getElementsByTagName("head")[0].appendChild(fileref);

    loadjscssfile(, "js") //dynamically load and add this .js file
</script>

并将我的测试移入(之前还需要参考 jquery)

    $(document).ready(function () {
        QUnit.test("Test #1 description", function () { ... });
    });

类似的方法也适用于纯测试文件。

【讨论】:

  • 这对于一个非常简单的任务来说太过分了。将脚本标签包含在文件的绝对路径中是完全相同的,唯一的区别是稍后添加,这在某些时候可能会成为单元测试的问题,因为您需要等待此脚本加载。还有一个主要问题,您无法使用此方法引用链接文件或网站之外的文件。您必须先复制它们,这可以通过 gulp 任务轻松实现自动化,无论哪种方式都不是一个好的解决方案。
  • 我不擅长 JavaScript 和配置/构建工具,所以如果我有任何可行的解决方案(特别是如果我通过了很长的路让它工作)我有时会停下来。
  • 问题在于,在您的情况下,您必须编写样板代码以确保在运行测试时加载脚本。不这样做的结果是,随着项目的发展,您最终会遇到不确定性测试。有时您的测试会无缘无故地失败,原因是您的测试执行并且脚本在几毫秒后完成加载。您必须消除所有可能导致测试失败的因素。这就是为什么动态添加 javascript 不是一个好主意的原因,除非确实合理或者它也是测试的一部分。
【解决方案4】:

就我而言,我想在我的 ASP.NET Web 应用程序中以及在 CI 服务器上运行我的测试。除了这里的其他信息,我还需要以下信息,否则我会遇到与 CI 服务器上的 OP 相同的错误:

  1. 向测试脚本添加一个或多个 require() 调用。
  2. NODE_PATH 环境变量设置为我的应用程序的根目录。

require() 的示例

在我的测试脚本中,我包含了一个 requires 块,条件允许我在 Web 浏览器中使用此脚本,而无需采用第三方等效项,例如 requirejs(这很方便。)

if (typeof(require) !== 'undefined') {
    require('lib/3rdparty/dist/3p.js');
    require('js/my.js');
    require('js/app.js');
}

设置示例NODE_PATH

下面,'wwwroot'/lib/ 和其他应用程序文件所在的路径。我的测试文件位于/tests/

使用bash

#!/bin/bash
cd 'wwwroot'
export NODE_PATH=`pwd`
qunit tests

使用powershell

#!/usr/bin/pwsh
cd 'wwwroot'
$env:NODE_PATH=(pwd)
qunit tests

这让我既可以在我的 ASP.NET Web 应用程序中运行测试,也可以使用脚本从 CI 服务器运行测试。

HTH。

【讨论】:

  • 注意:作为设置NODE_PATH 的替代方法,您可以在require() 调用中使用相对路径,例如require('../lib/3rdparty/dist/3p.js')
  • 它真的不适合我。我将 require("project.js") 放入我的 tests.js 代码并尝试运行 qunit,但它给了我错误,我的函数来自 project.js 的未定义...
【解决方案5】:

如果您想知道如何让您的测试在从命令行(而不是从浏览器!)运行时看到您的代码,这里是 Shaun Wilson 答案的扩展版本(不不是开箱即用的,但包含从哪里开始的好主意)

结构如下:

project
│   index.js <--- Your script with logic
└───test
        tests.html <--- QUnit tests included in standard HTML page for "running" locally
        tests.js <--- QUnit test code

让我们想象一下,在您的 index.js 中,您有以下内容:

function doSomething(arg) {
  // do smth
  return arg;
}

还有tests.js中的测试代码(不是说它可以是文件的整个内容——你不需要其他任何东西来工作):

QUnit.test( "test something", function( assert ) {
  assert.ok(doSomething(true));
});

从命令行运行

要使您的代码可以从测试中访问,您需要在脚本中添加两件事

首先是从测试中明确“导入”您的脚本。由于 JS 没有开箱即用的功能,我们需要使用来自 NPM 的require。为了让我们的测试在 HTML 中运行(当您从浏览器运行它时,require 未定义)添加简单检查:

// Add this in the beginning of tests.js
// Use "require" only if run from command line
if (typeof(require) !== 'undefined') {
    // It's important to define it with the very same name in order to have both browser and CLI runs working with the same test code
    doSomething = require('../index.js').doSomething;
}

但如果index.js 不公开任何内容,则将无法访问任何内容。因此,需要显式公开您想要测试的函数(阅读更多关于exports 的信息)。将此添加到 index.js:

//This goes to the very bottom of index.js
if (typeof module !== 'undefined' && module.exports) {
  exports.doSomething = doSomething; 
}

完成后,只需输入

qunit

输出应该是这样的

TAP version 13
ok 1 Testing index.js > returnTrue returns true
1..1
# pass 1
# skip 0
# todo 0
# fail 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2013-11-21
    相关资源
    最近更新 更多