Введение
Начиная с Visual Studio 2022, модульные тесты JavaScript можно легко обнаружить и запустить в Test Explorer Visual Studio. Это гораздо удобнее для разработки библиотеки классов Razor для Blazor. Когда я разрабатывал библиотеку классов Razor, содержащую вспомогательный код JavaScript для использования из кода C#, я часто хотел выполнить модульные тесты как для кода C#, так и для кода JavaScript. Visual Studio 2022 позволила мне это сделать.
Как это сделать?
Предположим, что у вас уже есть проект модульного тестирования для библиотеки классов Razor, в частности для кода на C#. В таком случае вы можете сделать так, чтобы этот проект модульного тестирования дополнительно выполнял тесты для кода JavaScript, просто добавив несколько шагов, как показано ниже.
1) Добавьте свойство <JavaScriptTestFramework>
в файл проекта модульного тестирования (.csproj), чтобы указать, какой фреймворк модульного тестирования JavaScript вы используете. А также добавьте свойство <JavaScriptTestRoot>
, чтобы указать относительный путь, по которому размещаются коды модульных тестов.
Следующий пример показывает использование “mocha”, одного из известных фреймворков для тестирования JavaScript.
<!-- A .csproj file of your unit test project -->
<Project Sdk="Microsoft.NET.Sdk">
...
<PropertyGroup>
<JavaScriptTestFramework>Mocha</JavaScriptTestFramework>
<JavaScriptTestRoot>tests</JavaScriptTestRoot>
</PropertyGroup>
...
2) Настройте среду модульного тестирования JavaScript. Например, чтобы использовать “mocha”, выполните следующие команды в терминальной консоли в каталоге тестового проекта.
(В качестве предпосылки в вашей среде должен быть установлен Node.js).
> npm init -y
> npm install --save-dev mocha
Не забудьте исключить папку “node_modules” из проекта юнит-тестов следующим образом:
<!-- A .csproj file of your unit test project -->
<Project Sdk="Microsoft.NET.Sdk">
...
<!-- 👇 exclude the "node_modules" folder for any purpose. -->
<ItemGroup>
<Compile Remove="node_modules**" />
<EmbeddedResource Remove="node_modules**" />
<None Remove="node_modules**" />
</ItemGroup>
...
3) Напишите код вашего модульного теста в соответствии с используемым фреймворком модульных тестов JavaScript.
// ./tests/fooTest.js
const assert = require("assert");
describe("fooTest", function () {
it('foo is bar', function () {
assert.ok("this test will alwasy pass.");
})
});
После этого вы увидите эти JavaScript юнит-тесты в Test Explorer, и сможете запускать их обычным для Visual Studio способом.
Для получения дополнительной информации, пожалуйста, смотрите также следующую ссылку на официальный сайт документа.
https://docs.microsoft.com/visualstudio/javascript/unit-testing-javascript-with-visual-studio?view=vs-2022&tabs=mocha
Написание кода тестов с помощью TypeScript
Конечно, мы можем написать коды тестов на JavaScript с помощью TypeScript. Например, для этого выполните следующие действия.
1) Установите NuGet-пакет “Microsoft.TypeScript.MSBuild” в проект модульного тестирования. Один из способов сделать это – выполнить команду dotnet add package
в каталоге проекта модульного тестирования следующим образом:
> dotnet add package Microsoft.TypeScript.MSBuild
2) Добавьте файлы определения типов (.d.ts) для TypeScript-кода, который вам нужен, следующим образом:
> npm install --save-dev @types/mocha @types/node
3) Добавьте файл “tsconfig.json” со следующим содержимым в каталог проекта юнит-тестов для настройки поведения компилятора TypeScript. (Пожалуйста, настройте конфигурацию “target” в соответствии с вашими потребностями).
// ./tsconfig.json
{
"compilerOptions": {
"target": "ES2017",
"module": "CommonJS",
"strict": true
},
"compileOnSave": true
}
После этого вы сможете писать коды модульных тестов на TypeScript следующим образом:
// ./tests/fooTest.ts
import * as assert from "assert";
import { describe, it } from "mocha";
describe('fooTest', function () {
it('foo is bar', function () {
assert.ok("this test will always pass.");
})
});
Проблема – несовместимая система модулей
Кстати, я также пишу вспомогательный JavaScript-код внутри библиотеки классов Razor – которая будет целью юнит-тестов в этом сценарии – на TypeScript.
И тип модульной системы у них должен быть “ES Module”, а не “CommonJS”, потому что эти JavaScript-коды будут вызываться из приложений Blazor с помощью IJSRuntime.InvokeAsync<IJSObjectReferense>("import", <путь .js файла>)
.
Например, tsconfig.json
в проекте Razor Class Library будет выглядеть следующим образом.
// tsconfig.json in a Razor Class Library project
{
"compilerOptions": {
...
"module": "ES2015", // 👈 Use the ES Module system, not CommonJS.
...
А скомпилированный код JavaScript, например, “CatClass”, будет иметь следующий вид.
// catClass.js in the Razor Class Library project
export class CatClass {
meows() {
return "Meow!!";
}
}
Но, к сожалению, “mocha” не работает с режимом ES Module на Visual Studio ожидаемо.
Я опущу подробности, но в любом случае, вы должны настроить коды модульных тестов для “mocha”, которые доступны для Visual Studio Test Explorer, на режим CommonJS.
Например, если у вас есть тестовый код, как показано ниже, который импортирует “catClass.js” в качестве тестовой цели,
// ./tests/catClassTest.ts in the unit test project
...
import { CatClass } from "../../RazorClassLibrary1/catClass";
describe('CatClass', function () {
it('meows', function () {
const cat = new CatClass();
assert.equal('Meow!', cat.meows());
});
});
вы столкнетесь с ошибкой “SyntaxError: Unexpected token ‘export'”, когда Visual Studio попытается обнаружить юнит-тесты, подобные приведенным выше.
(На самом деле, сама “mocha” может работать с ES Module mode начиная с ver.9. Но нет никакого способа включить ES Module mode “mocha”, когда Visual Studio обнаруживает или запускает тесты, чтобы это не привело к ошибке).
Что делать?
Мое решение – оно сложное, но работает
К счастью, все мои JavaScript-коды написаны на исходных кодах TypeScript.
Поэтому я решил решить эту проблему, скомпилировав все файлы TypeScript в режиме модуля “CommonJS” в папку проекта юнит-теста, причем не только файлы для юнит-теста, но и файлы для тестовой цели.
Давайте посмотрим, что я сделал.
Прежде всего, я поместил файлы TypeScript юнит-теста в корневую папку проекта юнит-теста.
Это важно для одновременной компиляции TypeScript-файлов, включая как код модульного теста, так и код библиотеки (тестовой цели).
Конечно, я также настроил путь импорта модуля тестовой цели (файл TypeScript) в файлах TypeScript юнит-теста, вот так:
// move the ./tests/catClassTest.ts to ./catClassTest.ts
// in the unit test project
...
// 👇 Fix the path of importing the test target module.
//import { CatClass } from "../../RazorClassLibrary1/catClass";
import { CatClass } from "../RazorClassLibrary1/catClass";
...
Далее я добавил две опции в конфигурацию компилятора TypeScript “tsconfig.json” в корневой папке проекта юнит-тестов.
Одна из них – добавление папки библиотеки классов Razor (она является тестовой целью) в папку compile target.
И еще один – это настройка выходной папки явно в соответствии со значением свойства <JavaScriptTestRoot>
в файле проекта юнит-теста (.csproj).
// ./tsconfig.json in the unit test project
{
"compilerOptions": {
...
// 👇 Add these two options.
"rootDirs": [ "./", "../RazorClassLibrary1" ],
"outDir": "./tests",
...
После того как я внес вышеуказанные изменения и пересобрал все решение, я получил результат, как показано на следующем рисунке.
Наконец, я смог правильно запустить JavaScript юнит-тесты в Visual Studio’s Test Explorer! 🎉
Заключение
Возможность запускать модульные тесты одновременно для C# и для JavaScript в Visual Studio Test Explorer UI очень удобна для меня при разработке библиотеки классов Razor для Blazor.
Но фреймворк для тестирования JavaScript “mocha” может работать только в режиме модуля CommonJS в Visual Studio Test Explorer, даже если тип модуля целевого JavaScript кода теста – ES Module.
К счастью, я всегда пишу код JavaScript на TypeScript, поэтому я решил эту проблему, дважды скомпилировав тестовые целевые файлы TypeScript в файлы JavaScript с разными модульными режимами (“ES Module” и “CommonJS”).
Пример кода был опубликован на репозитории GitHub по следующей ссылке:
https://github.com/sample-by-jsakamoto/Runs-JavaScript-tests-on-Visual-Studio-2022-Test-Explorer
Однако, на самом деле, я не уверен, что мое решение является лучшим.
Действительно, нет ли способа запустить “mocha” в режиме ES Module в Visual Studio Test Explorer?
Или же другой JavaScript фреймворк, такой как Jest, Jasmine и т.д., может позволить мне запустить его в режиме ES модуля?
Если у вас есть лучшее решение или идея, я буду благодарен, если вы поделитесь ими.
Учитесь, практикуйте, делитесь :).