Skip to content
狼叔 edited this page Feb 21, 2021 · 11 revisions

Welcome to the ts-junit wiki!

junit

ts decorators

核心定义 https://www.typescriptlang.org/docs/handbook/decorators.html#metadata

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

实现写法

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("A special test case")
class DisplayNameDemo {

    @Test
    @DisplayName("Custom test name containing spaces")
    void testWithDisplayNameContainingSpaces() {
    }

    @Test
    @DisplayName("╯°□°)╯")
    void testWithDisplayNameContainingSpecialCharacters() {
    }

    @Test
    @DisplayName("😱")
    void testWithDisplayNameContainingEmoji() {
    }

}

这里的DisplayName既可以放在class上,也可以放到property上。为了研究这个问题,参考typeorm的index写法,确认可行性,继而查找 https://github.com/typeorm/typeorm/blob/master/src/decorator/Index.ts#L58。

最终精简代码。

export function DisplayName(message: string): ClassDecorator & PropertyDecorator {
    console.dir(message)
    return function (clsOrObject: Function|Object, propertyName?: string | symbol) {
        console.dir(clsOrObject)
        console.dir(propertyName)
    }
}

play

经历

  • 最早设想是jest,很长一段没有动力
  • 研究发现uvu更简单,于是用uvu玩了一下。实现了基本的@Test
  • 遇到@DisplayName()同时可以在method和class上使用的问题,参考typeorm搞定,@Disabled同样原理
  • 实现@BeforeAll的时候,发现对象没有实例化,于是各种bind和call,搞定
  • 搞定申明周期的Before和After、BeforeEach和AfterEach
  • 对于装饰器用法我是不满意的。魔改一下require-dir,稍后去提pr。深度优先便利,将对象打平。这种思路和daruk,typeorm都不一样,但更好用。
    import { flatten } from './flatten'
    var requireDir = require('./require');

    var Classes = requireDir(dir, {
        recurse: true,
        extensions: ['.ts'],
        require: function (r, abs, folder) {
            var Clazz = r;
            var obj = new Clazz.default()

            //此处去加载装饰器
            const data = require('../index').data()

            //此处清空装饰器示例的data
            require('../index').emptydata()

            //此处去包装数据结构
            var obj = new Clazz.default()
            obj.__data = data
            var clz_name = obj.constructor.name
            return { clz_name, obj }
        }
    })

    let nodeList = flatten(Classes);

    console.log(nodeList);
Clone this wiki locally