ts-junit
v1.0.18
Published
use junit descrator with typescript
Downloads
193
Maintainers
Readme
ts-junit
use JUnit 5 Decrator with TypeScript
在我看来,在TypeScript里使用面向对象是很大概率变成最常用的方式的。目前所有的JavaScript测试都是面向过程的,比如qunit、jest、mocha、ava、tape等测试框架实现,还是围绕在面向过程阶段。我以为这不是TypeScript在现实中该有的样式。
我对Java还算熟悉,比如使用JUnit 5的测试代码就是采用面向对象写法的,代码如下。
import static org.junit.jupiter.api.Assertions.assertEquals;
import example.util.Calculator;
import org.junit.jupiter.api.Test;
class MyFirstJUnitJupiterTests {
private final Calculator calculator = new Calculator();
@Test
void addition() {
assertEquals(2, calculator.add(1, 1));
}
}
这种写法是非常简单的,这就是Java面向的好处。如果换成TypeScript,几乎可以保持写法一模一样,代码如下。
import assert from 'assert'
import { Test } from 'ts-junit'
export default class MyFirstJUnitJupiterTests {
calculator = new Calculator();
@Test
void addition() {
assert.is(2, calculator.add(1, 1));
}
}
反观前端的测试代码基本上2种风格。前端的测试代码风格1,它是最常用的测试方式,代码实例如下。
test('JSON', () => {
const input = {
foo: 'hello',
bar: 'world'
};
const output = JSON.stringify(input);
assert.snapshot(output, `{"foo":"hello","bar":"world"}`);
assert.equal(JSON.parse(output), input, 'matches original');
})
前端的测试代码风格2,bdd风格,它更强调行为对测试用例的影响,代码实例如下。
describe('User', function(){
describe('#save()', function(){
it('should save without error', function(done){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
});
})
})
})
对比一下Java和JavaScript测试多个写法之后,你会发现,面向对象在JavaScript(TypeScript)里根本不是一等公民。于是我就蒙发了一个想法,想用TypeScript实现一下JUnit。
特性
- ~~jest 支持 ts 需要引入babel~~
- ~~ts-jest 直接支持ts,测试语法上是jest语法,suite/test或describe/it~~
- ts-junit 使用junit 5的装饰器进行封装,成熟,使用于熟悉OO的开发,尤其对Java开发更友好。
- ts-junit 默认使用uvu,同时提供各个常见测试框架的支持,比如jest、mocha、ava、tape、qunit、jasmine等。
示例
import assert from 'assert'
import { BeforeAll, BeforeEach, Disabled, Test, AfterEach, AfterAll } from 'ts-junit'
export default class MyFirstJUnitJupiterTests {
calculator = new Calculator()
@BeforeAll
static void initAll() {
}
@BeforeEach
void init() {
}
@Test
void succeedingTest() {
}
@Test
void failingTest() {
assert.fail("a failing test");
}
@Test
@Disabled("for demonstration purposes")
void skippedTest() {
// not executed
}
@Test
void abortedTest() {
assert.assumeTrue("abc".contains("Z"));
assert.fail("test should have been aborted");
}
@AfterEach
void tearDown() {
}
@AfterAll
static void tearDownAll() {
}
}
Usages
方式1: 使用独立cli进行编译
不依赖当前项目的ts环境,直接通过cli执行,参考源码中tests目录下的文件。
$ npm i --global ts-juint
$ junit tests
$ junit tests/test.ts
编写第一个测试用例
import assert from 'assert'
import { Test } from 'ts-junit'
export default class MyFirstJUnitJupiterTests {
calculator = new Calculator();
@Test
void addition() {
assert.is(2, calculator.add(1, 1));
}
}
方式2: 依赖当前项目的ts环境进行编译
$ npm i --save-dev ts-juint
编写测试入口文件ts-junit.ts,文件内指定测试文件或测试目录即可。
import * as path from "node:path";
import { run } from "ts-junit";
const folder = path.resolve(process.cwd(), "./tests");
const file = path.resolve(process.cwd(), "./tests/test.ts");
run([folder, file]);
创建编译时的 tsconfig.json 文件
{
"compileOnSave": true,
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"sourceMap": true,
"outDir": "./build",
"rootDir": "./src",
"typeRoots": [],
"types": [],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"exclude": ["node_modules"],
"include": ["./src/**/*.ts", "./test/**/*.ts"]
}
编辑 package.json 的启动和编译脚本
{
"scripts": {
"test": "NODE_ENV=dev ts-node --project tsconfig.json --files ts-junit.ts",
"build": "tsc"
}
}
启动服务
$ npm test
> NODE_ENV=dev ts-node --project tsconfig.json --files ts-junit.ts
[2020-9-1 19:52:12] [debug] [init] [router] get - /
装饰器
- 参考junit5的文档 https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
- 进度
7/20
TODO
1) 结合 https://github.com/midwayjs/injection 更简单(暂未实现)
class Test {
@Inject()
helloTest: IHelloTest;
@Inject()
helloService: IHelloService;
@Before()
before() {
mock(helloTest, 'sayhello', () => {
return 'mocked'
});
}
@Test()
async test() {
expect(this.helloTest.sayhello()).eq('mocked');
expect(this.helloService.sayhello('test')).eq('hello test');
}
}
2) use vm2 with require from memfs