├── .gitignore
├── .idea
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── README_CN.md
├── build.gradle
├── doc
├── architecture.png
└── effect.mov
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
└── java
│ └── cn
│ └── net
│ └── fasttest
│ ├── FastSpringTest.java
│ ├── command
│ ├── Command.java
│ ├── CommandHandler.java
│ ├── CommandHandlerFactory.java
│ ├── CommandParser.java
│ └── handler
│ │ ├── HelpCommandHandler.java
│ │ ├── HistoryCommandHandler.java
│ │ ├── QuitCommandHandler.java
│ │ ├── ReRunCommandHandler.java
│ │ ├── RunCommandHandler.java
│ │ └── ShowCommandHandler.java
│ ├── configuration
│ └── Configuration.java
│ ├── event
│ ├── EventBus.java
│ ├── EventEnum.java
│ ├── FastSpringTestEvent.java
│ ├── FastSpringTestListener.java
│ └── Subscribe.java
│ ├── exception
│ └── FastTestException.java
│ ├── loader
│ ├── DefaultHotClassLoader.java
│ └── HotLoadClassLoader.java
│ ├── runner
│ ├── RunnerFactory.java
│ ├── TestRunResult.java
│ ├── TestRunner.java
│ ├── junit
│ │ ├── JunitRunner.java
│ │ └── JunitTestExecutionListener.java
│ └── testng
│ │ ├── TestNGListener.java
│ │ └── TestNGRunner.java
│ └── utils
│ └── FontColorUtil.java
└── test
└── java
└── cn
└── net
└── fasttest
├── FastSpringTests.java
├── command
├── CommandHandlerTest.java
└── CommandParserTest.java
├── event
└── EventTest.java
└── runner
├── JunitRunnerTest.java
└── TestNGRunnerTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**/build/
5 | !**/src/test/**/build/
6 |
7 | ### IntelliJ IDEA ###
8 | .idea/*
9 | .idea/modules.xml
10 | .idea/jarRepositories.xml
11 | .idea/compiler.xml
12 | .idea/libraries/
13 | *.iws
14 | *.iml
15 | *.ipr
16 | *.bak
17 | secring.gpg
18 | gradle.properties
19 | out/
20 | !**/src/main/**/out/
21 | !**/src/test/**/out/
22 |
23 | ### Eclipse ###
24 | .apt_generated
25 | .classpath
26 | .factorypath
27 | .project
28 | .settings
29 | .springBeans
30 | .sts4-cache
31 | bin/
32 | !**/src/main/**/bin/
33 | !**/src/test/**/bin/
34 |
35 | ### NetBeans ###
36 | /nbproject/private/
37 | /nbbuild/
38 | /dist/
39 | /nbdist/
40 | /.nb-gradle/
41 |
42 | ### VS Code ###
43 | .vscode/
44 |
45 | ### Mac OS ###
46 | .DS_Store
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | {
77 | "associatedIndex": 4
78 | }
79 |
80 |
81 |
82 |
83 |
84 |
85 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | true
151 | true
152 | false
153 | false
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | true
173 | true
174 | false
175 | false
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | true
195 | true
196 | false
197 | false
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | true
217 | true
218 | false
219 | false
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | true
239 | true
240 | false
241 | false
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 | 1704611530601
266 |
267 |
268 | 1704611530601
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/FastSpringTest.java
291 | 60
292 |
293 |
294 |
295 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/RunCommandHandler.java
296 | 27
297 |
298 |
299 |
300 | file://$PROJECT_DIR$/src/test/java/cn/net/fasttest/command/CommandParserTest.java
301 | 18
302 |
303 |
304 |
305 | file://$PROJECT_DIR$/src/test/java/cn/net/fasttest/command/CommandParserTest.java
306 | 23
307 |
308 |
309 |
310 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/ShowCommandHandler.java
311 | 37
312 |
313 |
314 |
315 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/ReRunCommandHandler.java
316 | 30
317 |
318 |
319 |
320 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/HistoryCommandHandler.java
321 | 35
322 |
323 |
324 |
325 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/FastSpringTest.java
326 | 36
327 |
328 |
329 |
330 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/ShowCommandHandler.java
331 | 60
332 |
333 |
334 |
335 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/RunCommandHandler.java
336 | 31
337 |
338 |
339 |
340 | file://$PROJECT_DIR$/src/main/java/cn/net/fasttest/command/handler/ShowCommandHandler.java
341 | 51
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Languages: English | [中文](README_CN.md)
2 | # fast-spring-test
3 | The unit test speed-up tool draws on spring test's support for integration testing, so that unit tests can also reuse the spring container without restarting the spring container to achieve the purpose of rapid unit testing. It supports multiple test engines junit4, junit5, testNG, etc.
4 |
5 | ## Architecture
6 |
7 | 
8 |
9 | ## Effects
10 |
11 |
12 | https://github.com/liubingmx/fast-spring-test/assets/20813546/00874ed7-e1b6-483c-8d3a-e40e46116142
13 |
14 | - The first run requires starting the running environment, which takes a long time. After the second run, the container can be reused, and the unit test execution time can be down to the millisecond level. There is no need to restart when adding a single test case. The test can be hot loaded and executed directly.
15 |
16 | ## Getting started
17 |
18 | ### Maven dependency
19 |
20 | ```xml
21 |
22 | 1.0.3
23 |
24 |
25 |
26 |
27 | cn.net.fasttest
28 | fast-spring-test
29 | test
30 | ${fast.spring.test.version}
31 |
32 |
33 | ```
34 |
35 | ### Add test entry
36 |
37 | ```java
38 | public class FastSpringApplicationTests {
39 |
40 | @Test
41 | public void test() {
42 |
43 | System.out.println("test...");
44 | Assertions.assertTrue(true);
45 | }
46 |
47 | public static void main(String[] args) {
48 | Configuration configuration = Configuration.ConfigurationBuilder.builder()
49 | .prompt("fast-spring-test-demo => ")
50 | .build();
51 | FastSpringTest.run(configuration);
52 | }
53 | }
54 | ```
55 | IDE run FastSpringApplicationTests, execute the following command to start testing
56 | ```
57 | # run com.xx.class#method
58 | run cn.net.fasttest.FastSpringApplicationTests#test
59 | # or
60 | cn.net.fasttest.FastSpringApplicationTests#test
61 | ```
62 | ### All Commands
63 | - run : Run test case,example:
64 | - run cn.net.fasttest.FastSpringTests#test
65 |
66 | - show : Show the results of the last run
67 |
68 | - rerun : Rerun last test case
69 |
70 | - history : Show the most recently executed command
71 |
72 | - help : Print help information for all commands
73 |
74 | - quit : Quit.
75 |
76 | ## Contributing
77 |
78 | - We welcome and encourage you to contribute to our projects. If you have any questions, suggestions, or want to contribute code, please contact us via email, GitHub issues, or submit a PR directly. Your participation will make this project even better!
79 |
80 | ## Reporting bugs
81 |
82 | - [GitHub Issue](https://github.com/liubingmx/fast-spring-test/issues/new)
83 |
84 | ## License
85 |
86 | fast-spring-test is under the Apache 2.0 license. See the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) file for details.
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 |
2 | Languages: 中文 [English](README.md)
3 | # fast-spring-test
4 | 单元测试提速工具,借鉴spring test对集成测试的支持,使单元测试也可以复用spring容器,不用重启spring容器,以达到快速单测的目的, 支持多种测试引擎junit4、junit5、testNG等
5 |
6 | ## 使用效果
7 |
8 |
9 | https://github.com/liubingmx/fast-spring-test/assets/20813546/00874ed7-e1b6-483c-8d3a-e40e46116142
10 |
11 | - 第一次运行需要启动运行环境,耗时较长, 第二次往后可复用容器,单元测试执行时间可至毫秒级别,增加单测case也不用重启,可热加载直接执行测试
12 |
13 | ## 快速开始
14 |
15 | ### Maven 依赖
16 |
17 | ```xml
18 |
19 | 1.0.3
20 |
21 |
22 |
23 |
24 | cn.net.fasttest
25 | fast-spring-test
26 | test
27 | ${fast.spring.test.version}
28 |
29 |
30 | ```
31 |
32 | ### 增加应用测试入口
33 |
34 | ```java
35 | public class FastSpringApplicationTests {
36 |
37 | @Test
38 | public void test() {
39 |
40 | System.out.println("test...");
41 | Assertions.assertTrue(true);
42 | }
43 |
44 | public static void main(String[] args) {
45 | Configuration configuration = Configuration.ConfigurationBuilder.builder()
46 | .prompt("fast-spring-test-demo => ")
47 | .build();
48 | FastSpringTest.run(configuration);
49 | }
50 | }
51 | ```
52 |
53 | 在你的IDE里右键运行 FastSpringApplicationTests,然后通过以下命令行执行单元测试
54 | ```
55 | # run com.xx.class#method
56 | run cn.net.fasttest.FastSpringApplicationTests#test
57 | # 或者
58 | cn.net.fasttest.FastSpringApplicationTests#test
59 | ```
60 |
61 | ### 命令列表
62 | - run : 运行单元测试,执行如下命令,cn.net.fasttest.FastSpringTests#test为单元测试全路径名,也可直接输入cn.net.fasttest.FastSpringTests#test:
63 | - run cn.net.fasttest.FastSpringTests#test
64 |
65 | - show : 展示最后一次运行的单元测试的运行结果
66 |
67 | - rerun : 重新运行最后一次运行的单测
68 |
69 | - history : 展示最近执行的命令
70 |
71 | - help : 输出所有命令的解释信息
72 | - quit : 退出程序
73 |
74 | ## Contributing
75 |
76 | - 我们非常欢迎并鼓励您为我们的项目做出贡献。如果您有任何问题、建议或想要贡献代码,请通过邮件、GitHub issues或直接提交PR与我们联系。您的参与将使这个项目更加完美!
77 |
78 | ## 提交bug
79 |
80 | - [GitHub Issue](https://github.com/liubingmx/fast-spring-test/issues/new)
81 |
82 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | id 'maven-publish'
4 | id 'signing'
5 | }
6 |
7 |
8 | group = 'cn.net.fasttest'
9 | archivesBaseName = "fast-spring-test"
10 | version = '1.0.3'
11 |
12 | repositories {
13 | mavenCentral()
14 | }
15 |
16 |
17 | javadoc {
18 | options.tags = [ "create" ]
19 | }
20 |
21 | java {
22 | withJavadocJar()
23 | withSourcesJar()
24 | }
25 |
26 | publishing {
27 | publications {
28 | mavenJava(MavenPublication) {
29 | artifactId = 'fast-spring-test'
30 | from components.java
31 | versionMapping {
32 | usage('java-api') {
33 | fromResolutionOf('runtimeClasspath')
34 | }
35 | usage('java-runtime') {
36 | fromResolutionResult()
37 | }
38 | }
39 | pom {
40 | name='fast-spring-test'
41 | // optionally artifactId can be defined here
42 | description='Unit testing speedup tool.'
43 | url='https://github.com/liubingmx/fast-spring-test'
44 |
45 | scm {
46 | connection='cm:git://github.com/liubingmx/fast-spring-test'
47 | developerConnection='scm:git:https://github.com/liubingmx/fast-spring-test.git'
48 | url='https://github.com/liubingmx/fast-spring-test'
49 | }
50 |
51 | licenses {
52 | license {
53 | name='The Apache License, Version 2.0'
54 | url='http://www.apache.org/licenses/LICENSE-2.0.txt'
55 | }
56 | }
57 |
58 | developers {
59 | developer {
60 | id='rocco'
61 | name='rocco'
62 | email='liubingmx@163.com'
63 | }
64 | }
65 | }
66 | }
67 | }
68 | repositories {
69 | maven {
70 | name = "OSSRH"
71 | url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
72 | credentials {
73 | username = ossrhUsername
74 | password = ossrhPassword
75 | }
76 | }
77 |
78 | maven {
79 | name = "ossrhSnapshot"
80 | url = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
81 | credentials {
82 | username = ossrhUsername
83 | password = ossrhPassword
84 | }
85 | }
86 | }
87 | }
88 |
89 | signing {
90 | sign publishing.publications.mavenJava
91 | }
92 |
93 |
94 |
95 | dependencies {
96 | implementation platform('org.junit:junit-bom:5.9.1')
97 | implementation 'org.junit.jupiter:junit-jupiter'
98 | implementation 'org.junit.platform:junit-platform-launcher'
99 | implementation 'org.junit.vintage:junit-vintage-engine'
100 | implementation 'org.jline:jline:3.25.0'
101 | implementation 'org.testng:testng:7.7.0'
102 | }
103 |
104 | test {
105 | useJUnitPlatform()
106 | useTestNG()
107 | }
--------------------------------------------------------------------------------
/doc/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubingmx/fast-spring-test/9e461d69a33099d3d1f76dfa7772b5eb2d049669/doc/architecture.png
--------------------------------------------------------------------------------
/doc/effect.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubingmx/fast-spring-test/9e461d69a33099d3d1f76dfa7772b5eb2d049669/doc/effect.mov
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubingmx/fast-spring-test/9e461d69a33099d3d1f76dfa7772b5eb2d049669/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Jan 07 15:12:10 CST 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'fast-spring-test'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/FastSpringTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest;
2 |
3 | import cn.net.fasttest.command.CommandHandlerFactory;
4 | import cn.net.fasttest.command.CommandParser;
5 | import cn.net.fasttest.configuration.Configuration;
6 | import cn.net.fasttest.event.EventBus;
7 | import cn.net.fasttest.event.EventEnum;
8 | import cn.net.fasttest.event.FastSpringTestEvent;
9 | import cn.net.fasttest.exception.FastTestException;
10 | import cn.net.fasttest.command.Command;
11 | import cn.net.fasttest.utils.FontColorUtil;
12 | import org.jline.reader.EndOfFileException;
13 | import org.jline.reader.LineReader;
14 | import org.jline.reader.LineReaderBuilder;
15 | import org.jline.reader.impl.DefaultHighlighter;
16 | import org.jline.reader.impl.history.DefaultHistory;
17 | import org.jline.terminal.Terminal;
18 | import org.jline.terminal.TerminalBuilder;
19 |
20 | import java.io.IOException;
21 |
22 | /**
23 | * @author liubingmx@163.com
24 | * @create 2024/01/07
25 | */
26 | public class FastSpringTest {
27 |
28 | static {
29 | CommandHandlerFactory.init();
30 | }
31 | public static void run() {
32 | run(Configuration.ConfigurationBuilder.builder().build());
33 | }
34 |
35 | public static void run(Configuration configuration) {
36 |
37 | LineReader lineReader = getLineReader();
38 | EventBus.publishEvent(new FastSpringTestEvent(EventEnum.STARTED, lineReader));
39 | while (true) {
40 | try {
41 | String commandLine = lineReader.readLine(configuration.getPrompt()).trim();
42 | if (commandLine.isEmpty()) {
43 | continue;
44 | }
45 | Command command = ((CommandParser)lineReader.getParser()).parseCommand(commandLine);
46 | CommandHandlerFactory.getCommandHandler(command.getName()).run(command);
47 | EventBus.publishEvent(new FastSpringTestEvent(EventEnum.EXECUTE_COMMAND, command));
48 | } catch (FastTestException e) {
49 | System.out.println("\n" + FontColorUtil.format(e.getMessage(), FontColorUtil.RED));
50 | } catch (EndOfFileException e) {
51 | System.out.println("\nBye ~ ");
52 | break;
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | System.out.println("error " + e.getMessage());
56 | }
57 |
58 |
59 | }
60 | }
61 |
62 |
63 |
64 | private static LineReader getLineReader() {
65 | System.setProperty("org.jline.terminal.exec.redirectPipeCreationMode", "native");
66 | Terminal terminal;
67 | try {
68 | terminal = TerminalBuilder.builder()
69 | .system(true)
70 | .color(true)
71 | .dumb(true)
72 | .build();
73 | } catch (IOException e) {
74 | throw new RuntimeException(e);
75 | }
76 |
77 | return LineReaderBuilder.builder()
78 | .terminal(terminal)
79 | .history(new DefaultHistory())
80 | .highlighter(new DefaultHighlighter())
81 | .parser(new CommandParser())
82 | .build();
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/Command.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @author bing
8 | * @create 2024/01/07
9 | */
10 | public class Command {
11 |
12 | private String name;
13 |
14 | private String description;
15 |
16 | private List options;
17 |
18 |
19 | public Command(String command, String description, List options) {
20 | this.name = command;
21 | this.description = description;
22 | this.options = options;
23 | }
24 |
25 | public Command(String name, String description) {
26 | this.name = name;
27 | this.description = description;
28 | }
29 |
30 | public Command(String commandName, Option option) {
31 | this.name = commandName;
32 | this.options = new ArrayList<>();
33 | this.options.add(option);
34 | }
35 |
36 | public String getName() {
37 | return name;
38 | }
39 |
40 | public void setName(String name) {
41 | this.name = name;
42 | }
43 |
44 | public String getDescription() {
45 | return description;
46 | }
47 |
48 | public void setDescription(String description) {
49 | this.description = description;
50 | }
51 |
52 | public List getOptions() {
53 | return options;
54 | }
55 |
56 | public void setOptions(List options) {
57 | this.options = options;
58 | }
59 |
60 | public static class Option{
61 |
62 | private String args;
63 |
64 | private String description;
65 |
66 | public Option(String args) {
67 | this.args = args;
68 | }
69 |
70 | public String getArgs() {
71 | return args;
72 | }
73 |
74 | public void setArgs(String args) {
75 | this.args = args;
76 | }
77 |
78 | public String getDescription() {
79 | return description;
80 | }
81 |
82 | public void setDescription(String description) {
83 | this.description = description;
84 | }
85 | }
86 |
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/CommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | /**
4 | * @author bing
5 | * @create 2024/01/07
6 | */
7 | public interface CommandHandler {
8 |
9 | /**
10 | * get command
11 | * @return command
12 | */
13 | Command getCommand();
14 |
15 | /**
16 | * run the command
17 | * @param command args
18 | */
19 | void run(Command command);
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/CommandHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | import cn.net.fasttest.command.handler.*;
4 | import cn.net.fasttest.event.EventBus;
5 | import cn.net.fasttest.exception.FastTestException;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | /**
11 | * @author bing
12 | * @create 2024/01/07
13 | */
14 | public class CommandHandlerFactory {
15 |
16 | private static List handlers = new ArrayList<>();
17 |
18 | public static void init() {
19 | ShowCommandHandler showCommandHandler = new ShowCommandHandler();
20 | ReRunCommandHandler reRunCommandHandler = new ReRunCommandHandler();
21 | HistoryCommandHandler historyCommandHandler = new HistoryCommandHandler();
22 | register(new RunCommandHandler());
23 | register(showCommandHandler);
24 | register(reRunCommandHandler);
25 | register(historyCommandHandler);
26 | register(new HelpCommandHandler());
27 | EventBus.addListener(showCommandHandler);
28 | EventBus.addListener(reRunCommandHandler);
29 | EventBus.addListener(historyCommandHandler);
30 | register(new QuitCommandHandler());
31 | }
32 |
33 | public static void register(CommandHandler commandHandler) {
34 | handlers.add(commandHandler);
35 | }
36 |
37 | public static CommandHandler getCommandHandler(String commandName) {
38 | return handlers.stream()
39 | .filter(e -> e.getCommand().getName().equalsIgnoreCase(commandName))
40 | .findFirst()
41 | .orElseThrow(() -> new FastTestException("【 " + commandName + " 】This command is not currently supported"));
42 |
43 | }
44 |
45 | public static List getAllCommandHandlers() {
46 | return handlers;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/CommandParser.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | import org.jline.reader.impl.DefaultParser;
4 |
5 | /**
6 | * @author liubingmx@163.com
7 | * @create 2024/01/11
8 | */
9 | public class CommandParser extends DefaultParser {
10 |
11 | private static final String DEFAULT_COMMAND = "run";
12 | private static final String EMPTY_STR = "";
13 |
14 | public Command parseCommand(String line) {
15 | return new Command(getCommandStr(line), getOption(line));
16 | }
17 |
18 | Command.Option getOption(final String line) {
19 | String option = line.replace(getCommand(line), EMPTY_STR).trim();
20 | return new Command.Option(option);
21 | }
22 |
23 | public String getCommandStr(final String line) {
24 | String command = getCommand(line);
25 | if (!EMPTY_STR.equals(command.trim())) {
26 | return command;
27 | }
28 | return DEFAULT_COMMAND;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/HelpCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.Command;
4 | import cn.net.fasttest.command.CommandHandler;
5 | import cn.net.fasttest.command.CommandHandlerFactory;
6 | import cn.net.fasttest.utils.FontColorUtil;
7 |
8 | import java.sql.SQLOutput;
9 | import java.util.List;
10 |
11 | /**
12 | * @author bing
13 | * @create 2024/01/21
14 | */
15 | public class HelpCommandHandler implements CommandHandler {
16 | @Override
17 | public Command getCommand() {
18 | return new Command("help", "Print help information for all commands");
19 | }
20 |
21 | @Override
22 | public void run(Command command) {
23 | System.out.println("--------------------------HELP INFO--------------------------");
24 | List allCommandHandlers = CommandHandlerFactory.getAllCommandHandlers();
25 | for (CommandHandler commandHandler : allCommandHandlers) {
26 | System.out.printf("%s : %s \n", FontColorUtil.format(commandHandler.getCommand().getName(), FontColorUtil.BULE),
27 | commandHandler.getCommand().getDescription());
28 |
29 | System.out.println();
30 | }
31 | System.out.println("------------------------DEFAULT COMMAND------------------------");
32 | System.out.println("If you enter the command directly and it is not the above command, the run command will be executed by default. " +
33 | "For example\n cn.net.fasttest.FastSpringTests#test <==> run cn.net.fasttest.FastSpringTests#test");
34 |
35 | System.out.println("---------------------------------------------------------------");
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/HistoryCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.Command;
4 | import cn.net.fasttest.command.CommandHandler;
5 | import cn.net.fasttest.event.EventEnum;
6 | import cn.net.fasttest.event.FastSpringTestEvent;
7 | import cn.net.fasttest.event.FastSpringTestListener;
8 | import cn.net.fasttest.event.Subscribe;
9 | import org.jline.reader.History;
10 | import org.jline.reader.LineReader;
11 |
12 | /**
13 | * @author liubingmx@163.com
14 | * @create 2024/01/12
15 | */
16 | public class HistoryCommandHandler implements CommandHandler, FastSpringTestListener {
17 |
18 | History defaultHistory;
19 |
20 | @Override
21 | public Command getCommand() {
22 | return new Command("history", "Show the most recently executed command");
23 | }
24 |
25 | @Override
26 | public void run(Command command) {
27 | for (History.Entry entry : defaultHistory) {
28 | System.out.println(entry);
29 | }
30 | }
31 |
32 | @Override
33 | @Subscribe(EventEnum.STARTED)
34 | public void listen(FastSpringTestEvent event) {
35 | this.defaultHistory = ((LineReader)event.getSource()).getHistory();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/QuitCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.Command;
4 | import cn.net.fasttest.command.CommandHandler;
5 | import org.jline.reader.EndOfFileException;
6 |
7 | /**
8 | * @author bing
9 | * @create 2024/03/07
10 | */
11 | public class QuitCommandHandler implements CommandHandler {
12 | @Override
13 | public Command getCommand() {
14 | return new Command("quit", "quit.");
15 | }
16 |
17 | @Override
18 | public void run(Command command) {
19 | throw new EndOfFileException();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/ReRunCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.CommandHandler;
4 | import cn.net.fasttest.event.EventEnum;
5 | import cn.net.fasttest.event.FastSpringTestEvent;
6 | import cn.net.fasttest.event.FastSpringTestListener;
7 | import cn.net.fasttest.command.Command;
8 | import cn.net.fasttest.command.CommandHandlerFactory;
9 | import cn.net.fasttest.event.Subscribe;
10 | import cn.net.fasttest.exception.FastTestException;
11 |
12 | /**
13 | * @author bing
14 | * @create 2024/01/14
15 | */
16 | public class ReRunCommandHandler implements CommandHandler, FastSpringTestListener {
17 |
18 | Command lasRunCommand;
19 |
20 | @Override
21 | public Command getCommand() {
22 | return new Command("rerun", "Rerun last test case");
23 | }
24 |
25 | @Override
26 | public void run(Command command) {
27 | if (lasRunCommand == null) {
28 | throw new FastTestException("Please execute the run command first ");
29 | }
30 | CommandHandlerFactory.getCommandHandler(lasRunCommand.getName()).run(lasRunCommand);
31 | }
32 |
33 | @Override
34 | @Subscribe(EventEnum.EXECUTE_COMMAND)
35 | public void listen(FastSpringTestEvent event) {
36 | if (!(event.getSource() instanceof Command)) {
37 | return;
38 | }
39 | Command lastCommand = (Command)event.getSource();
40 | if (!lastCommand.getName().equalsIgnoreCase(new RunCommandHandler().getCommand().getName())) {
41 | return;
42 | }
43 | lasRunCommand = lastCommand;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/RunCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.CommandHandler;
4 | import cn.net.fasttest.exception.FastTestException;
5 | import cn.net.fasttest.loader.HotLoadClassLoader;
6 | import cn.net.fasttest.runner.RunnerFactory;
7 | import cn.net.fasttest.command.Command;
8 | import cn.net.fasttest.loader.DefaultHotClassLoader;
9 |
10 | import java.util.Optional;
11 |
12 | /**
13 | * @author liubingmx@163.com
14 | * @create 2024/01/07
15 | */
16 | public class RunCommandHandler implements CommandHandler {
17 |
18 | private HotLoadClassLoader hotLoadClassLoader = new DefaultHotClassLoader();
19 |
20 | public RunCommandHandler() {
21 | }
22 |
23 | @Override
24 | public Command getCommand() {
25 | return new Command("run", "Run test case,example:\n \trun cn.net.fasttest.FastSpringTests#test");
26 | }
27 |
28 | @Override
29 | public void run(Command command) {
30 | Optional first = command.getOptions().stream().findFirst();
31 | String args = first.get().getArgs();
32 | if (args.trim().isEmpty()) {
33 | throw new FastTestException("Please enter correct parameters");
34 | }
35 | String[] classNameAndMethodName = args.split("#");
36 | Class> clazz = hotLoadClassLoader.loadTestClass(classNameAndMethodName[0]);
37 | String methodName = classNameAndMethodName.length > 1 ? classNameAndMethodName[1] : null;
38 | RunnerFactory.getRunner(methodName, clazz).run(clazz, methodName);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/command/handler/ShowCommandHandler.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command.handler;
2 |
3 | import cn.net.fasttest.command.Command;
4 | import cn.net.fasttest.command.CommandHandler;
5 | import cn.net.fasttest.event.EventEnum;
6 | import cn.net.fasttest.event.FastSpringTestEvent;
7 | import cn.net.fasttest.event.FastSpringTestListener;
8 | import cn.net.fasttest.event.Subscribe;
9 | import cn.net.fasttest.runner.TestRunResult;
10 | import cn.net.fasttest.utils.FontColorUtil;
11 |
12 | /**
13 | * @author liubingmx@163.com
14 | * @create 2024/01/12
15 | */
16 | public class ShowCommandHandler implements CommandHandler, FastSpringTestListener {
17 |
18 | TestRunResult lastRunResult;
19 |
20 | @Override
21 | public Command getCommand() {
22 | return new Command("show", "Show the results of the last run");
23 | }
24 |
25 | @Override
26 | public void run(Command command) {
27 | showResult();
28 | }
29 |
30 | private void log(String content, Object... args) {
31 | System.out.println(String.format(content, args));
32 | }
33 |
34 | @Override
35 | @Subscribe(EventEnum.RUN_TESTCASE)
36 | public void listen(FastSpringTestEvent event) {
37 | if (!(event.getSource() instanceof TestRunResult)) {
38 | return;
39 | }
40 | lastRunResult = (TestRunResult)event.getSource();
41 | showResult();
42 | }
43 |
44 | private void showResult() {
45 | if (TestRunResult.state.SUCCESSFUL.name().equals(lastRunResult.getState())) {
46 | log("------------------------execution finished : %s" + "------------------------", FontColorUtil.format("√ " + lastRunResult.getDisplayName(), FontColorUtil.BULE));
47 | } else {
48 | log("------------------------execution failed : %s" + "------------------------", FontColorUtil.format("× " + lastRunResult.getDisplayName(), FontColorUtil.RED));
49 | System.out.println();
50 | if (lastRunResult.getThrowable() != null) {
51 | lastRunResult.getThrowable().printStackTrace(System.out);
52 | }
53 | }
54 | System.out.println();
55 | if (lastRunResult.getTotalTestCount() != lastRunResult.getStarted()) {
56 | return;
57 | }
58 | log("--------------------------------- Summary ---------------------------------");
59 | log("RUN %s", lastRunResult.getUniqueId());
60 | log("Result -- started:%d -- succeeded: %d -- failed: %d -- skipped: %d -- cost: %d ms",
61 | lastRunResult.getStarted(), lastRunResult.getSucceeded(), lastRunResult.getFailed(),
62 | lastRunResult.getSkipped(), lastRunResult.getCost());
63 |
64 | log("You can use \"SHOW\" command to see detail.");
65 | log("You can use \"RERUN\" command to rerun these cases.");
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/configuration/Configuration.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.configuration;
2 |
3 | import cn.net.fasttest.utils.FontColorUtil;
4 |
5 | /**
6 | * @author bing
7 | * create 2024/01/07
8 | */
9 | public class Configuration {
10 |
11 | /**
12 | * cli prompt
13 | */
14 | private String prompt;
15 |
16 | private String promptColor;
17 |
18 |
19 | public Configuration(ConfigurationBuilder builder) {
20 | this.prompt = builder.getPrompt();
21 | this.promptColor = builder.getPromptColor();
22 | }
23 |
24 | public String getPrompt() {
25 | return FontColorUtil.format(prompt, promptColor);
26 | }
27 |
28 | public static class ConfigurationBuilder {
29 | private String prompt = "\033[1;34mFast-Spring-Test ->\033[0m";
30 |
31 | private String promptColor = FontColorUtil.BULE;
32 |
33 | private ConfigurationBuilder() {
34 | }
35 |
36 | public static ConfigurationBuilder builder() {
37 | return new ConfigurationBuilder();
38 | }
39 |
40 | public ConfigurationBuilder prompt(String prompt) {
41 | this.prompt = prompt;
42 | return this;
43 | }
44 |
45 | public ConfigurationBuilder promptColor(String promptColor) {
46 | this.promptColor = promptColor;
47 | return this;
48 | }
49 |
50 | public Configuration build() {
51 | return new Configuration(this);
52 | }
53 |
54 | public String getPrompt() {
55 | return prompt;
56 | }
57 |
58 | public String getPromptColor() {
59 | return promptColor;
60 | }
61 | }
62 |
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/event/EventBus.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | import cn.net.fasttest.exception.FastTestException;
4 |
5 | import java.lang.reflect.Method;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * @author liubingmx@163.com
11 | * @create 2024/01/12
12 | */
13 | public class EventBus {
14 |
15 | private static List listeners = new ArrayList<>();
16 |
17 | public static synchronized void addListener(FastSpringTestListener fastSpringTestListener) {
18 | listeners.add(fastSpringTestListener);
19 | }
20 |
21 | public static void publishEvent(FastSpringTestEvent event) {
22 | for (FastSpringTestListener listener : listeners) {
23 | // 获取指定方法上的注解
24 | Subscribe annotation;
25 | try {
26 | Method method = listener.getClass().getMethod("listen", FastSpringTestEvent.class);
27 | annotation = method.getAnnotation(Subscribe.class);
28 | } catch (NoSuchMethodException e) {
29 | throw new FastTestException(e.getMessage());
30 | }
31 | if (annotation !=null && !event.getEvent().equals(annotation.value())) {
32 | continue;
33 | }
34 | listener.listen(event);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/event/EventEnum.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | /**
4 | * @author liubingmx@163.com
5 | * @create 2024/01/12
6 | */
7 | public enum EventEnum {
8 |
9 | /**
10 | * application started event
11 | */
12 | STARTED,
13 |
14 | /**
15 | * Execute command event
16 | */
17 | EXECUTE_COMMAND,
18 |
19 | /**
20 | * Test case run event
21 | */
22 | RUN_TESTCASE,
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/event/FastSpringTestEvent.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | import java.util.EventObject;
4 |
5 | /**
6 | * @author liubingmx@163.com
7 | * @create 2024/01/12
8 | */
9 | public class FastSpringTestEvent extends EventObject {
10 |
11 | private EventEnum event;
12 |
13 | /**
14 | * Constructs a prototypical Event.
15 | *
16 | * @param event event
17 | * @param source the object on which the Event initially occurred
18 | * @throws IllegalArgumentException if source is null
19 | */
20 | public FastSpringTestEvent(EventEnum event,Object source) {
21 | super(source);
22 | this.event = event;
23 | }
24 |
25 | public EventEnum getEvent() {
26 | return event;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/event/FastSpringTestListener.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | import java.util.EventListener;
4 |
5 | /**
6 | * @author liubingmx@163.com
7 | * @create 2024/01/12
8 | */
9 | public interface FastSpringTestListener extends EventListener {
10 |
11 | /**
12 | * This method is called when the subscribed event occurs
13 | * @param event event Object
14 | */
15 | void listen(FastSpringTestEvent event);
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/event/Subscribe.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | /**
7 | * @author bing
8 | * @create 2024/01/22
9 | */
10 | @Retention(RetentionPolicy.RUNTIME)
11 | public @interface Subscribe {
12 |
13 | EventEnum value();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/exception/FastTestException.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.exception;
2 |
3 | /**
4 | * @author liubingmx@163.com
5 | * @create 2024/01/07
6 | */
7 | public class FastTestException extends RuntimeException{
8 |
9 | public FastTestException(String message) {
10 | super(message);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/loader/DefaultHotClassLoader.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.loader;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.Files;
5 | import java.nio.file.Path;
6 |
7 | /**
8 | * @author liubingmx@163.com
9 | * @create 2024/01/07
10 | */
11 | public class DefaultHotClassLoader implements HotLoadClassLoader{
12 |
13 | @Override
14 | public Class> loadTestClass(String testClassName) {
15 | try {
16 | return new InnerHotLoadClassLoader(testClassName).loadClass(testClassName);
17 | } catch (ClassNotFoundException e) {
18 | throw new RuntimeException(e);
19 | }
20 | }
21 |
22 |
23 | private static class InnerHotLoadClassLoader extends ClassLoader{
24 |
25 | private String loadClassName;
26 |
27 | public InnerHotLoadClassLoader(String loadClassName) {
28 | this.loadClassName = loadClassName;
29 | }
30 |
31 | @Override
32 | public Class> loadClass(String name) throws ClassNotFoundException {
33 | return findClass(name);
34 | }
35 |
36 | @Override
37 | public Class> findClass(String testClassName) throws ClassNotFoundException {
38 | if (testClassName == null) {
39 | return null;
40 | }
41 | if (!testClassName.equals(loadClassName)) {
42 | return Thread.currentThread().getContextClassLoader().loadClass(testClassName);
43 | }
44 | String fileName = testClassName.replaceAll("\\.", "/") + ".class";
45 | fileName = (getClass().getResource("/") + fileName).substring(5);
46 | try {
47 | byte[] data = Files.readAllBytes(Path.of(fileName));
48 | return defineClass(testClassName, data, 0, data.length);
49 | } catch (IOException e) {
50 | throw new RuntimeException(e);
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/loader/HotLoadClassLoader.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.loader;
2 |
3 | /**
4 | * @author liubingmx@163.com
5 | * @create 2024/01/07
6 | */
7 | public interface HotLoadClassLoader {
8 |
9 | /**
10 | * hot load test class
11 | * @param testClassName class name
12 | * @return clazz
13 | */
14 | Class> loadTestClass(String testClassName);
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/RunnerFactory.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner;
2 |
3 | import cn.net.fasttest.runner.junit.JunitRunner;
4 | import cn.net.fasttest.runner.testng.TestNGRunner;
5 |
6 | import java.lang.annotation.Annotation;
7 | import java.lang.reflect.Method;
8 | import java.util.Map;
9 | import java.util.Objects;
10 | import java.util.Set;
11 | import java.util.concurrent.ConcurrentHashMap;
12 |
13 | /**
14 | * @author liubingmx@163.com
15 | * @create 2024/01/07
16 | */
17 | public class RunnerFactory {
18 |
19 | private static Map runnerMap = new ConcurrentHashMap<>();
20 |
21 | static {
22 | register("org.junit.jupiter.api.Test", new JunitRunner());
23 | register("org.junit.Test", new JunitRunner());
24 | register("org.testng.annotations.Test", new TestNGRunner());
25 | }
26 |
27 | public static void register(String name, TestRunner runner) {
28 | runnerMap.put(name, runner);
29 | }
30 |
31 | public static Class extends Annotation> getClassByName(String className) throws ClassNotFoundException {
32 | Class> rawClass = Class.forName(className);
33 | if (!rawClass.isAnnotation()) {
34 | throw new IllegalArgumentException("Class is not an annotation: " + className);
35 | }
36 | return rawClass.asSubclass(Annotation.class);
37 | }
38 |
39 | public static Set getRunnerNames() {
40 | return runnerMap.keySet();
41 | }
42 |
43 | public static TestRunner getRunner(String methodName, Class> clazz) {
44 | Set runnerNames = runnerMap.keySet();
45 | for (String runnerName : runnerNames) {
46 | try {
47 | Class extends Annotation> testAnnotationClazz = getClassByName(runnerName);
48 | Annotation testAnnotation = clazz.getAnnotation(testAnnotationClazz);
49 | if (Objects.nonNull(testAnnotation)) {
50 | return runnerMap.get(runnerName);
51 | }
52 | if (methodName != null) {
53 | Method method = clazz.getDeclaredMethod(methodName);
54 | testAnnotation = method.getAnnotation(testAnnotationClazz);
55 | if (Objects.nonNull(testAnnotation)) {
56 | return runnerMap.get(runnerName);
57 | }
58 | }
59 | Method[] methods = clazz.getMethods();
60 | for (Method method : methods) {
61 | testAnnotation = method.getAnnotation(testAnnotationClazz);
62 | if (Objects.nonNull(testAnnotation)) {
63 | return runnerMap.get(runnerName);
64 | }
65 | }
66 | } catch (ClassNotFoundException e) {
67 | continue;
68 | }catch (NoSuchMethodException | ClassCastException e){
69 | throw new RuntimeException(e);
70 | }
71 | }
72 | throw new RuntimeException("not support this test engine");
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/TestRunResult.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner;
2 |
3 | import org.junit.platform.engine.TestExecutionResult;
4 |
5 | /**
6 | * @author liubingmx@163.com
7 | * @create 2024/01/12
8 | */
9 | public class TestRunResult {
10 |
11 | private String uniqueId;
12 |
13 | /**
14 | * @see TestExecutionResult.Status
15 | */
16 | private String state;
17 | private String displayName;
18 | private long cost;
19 |
20 | private long totalTestCount;
21 | private long started;
22 | private long succeeded;
23 | private long failed;
24 | private long skipped;
25 |
26 | public long getTotalTestCount() {
27 | return totalTestCount;
28 | }
29 |
30 | public void setTotalTestCount(long totalTestCount) {
31 | this.totalTestCount = totalTestCount;
32 | }
33 |
34 | public void setCost(long cost) {
35 | this.cost = cost;
36 | }
37 |
38 | public long getStarted() {
39 | return started;
40 | }
41 |
42 | public void setStarted(long started) {
43 | this.started = started;
44 | }
45 |
46 | public long getSucceeded() {
47 | return succeeded;
48 | }
49 |
50 | public void setSucceeded(long succeeded) {
51 | this.succeeded = succeeded;
52 | }
53 |
54 | public long getFailed() {
55 | return failed;
56 | }
57 |
58 | public void setFailed(long failed) {
59 | this.failed = failed;
60 | }
61 |
62 | public long getSkipped() {
63 | return skipped;
64 | }
65 |
66 | public void setSkipped(long skipped) {
67 | this.skipped = skipped;
68 | }
69 |
70 | public void setSkipped(int skipped) {
71 | this.skipped = skipped;
72 | }
73 |
74 | private Throwable throwable;
75 |
76 | public String getDisplayName() {
77 | return displayName;
78 | }
79 |
80 | public void setDisplayName(String displayName) {
81 | this.displayName = displayName;
82 | }
83 |
84 | public Throwable getThrowable() {
85 | return throwable;
86 | }
87 |
88 | public void setThrowable(Throwable throwable) {
89 | this.throwable = throwable;
90 | }
91 |
92 | public String getUniqueId() {
93 | return uniqueId;
94 | }
95 |
96 | public void setUniqueId(String uniqueId) {
97 | this.uniqueId = uniqueId;
98 | }
99 |
100 | public String getState() {
101 | return state;
102 | }
103 |
104 | public void setState(String state) {
105 | this.state = state;
106 | }
107 |
108 | public Long getCost() {
109 | return cost;
110 | }
111 |
112 | public void setCost(Long cost) {
113 | this.cost = cost;
114 | }
115 |
116 | /**
117 | * Status of executing a single test or container.
118 | */
119 | public enum state {
120 |
121 | /**
122 | * Indicates that the execution of a test or container was
123 | * successful.
124 | */
125 | SUCCESSFUL,
126 |
127 | /**
128 | * Indicates that the execution of a test or container was
129 | * aborted (started but not finished).
130 | */
131 | ABORTED,
132 |
133 | /**
134 | * Indicates that the execution of a test or container failed.
135 | */
136 | FAILED;
137 |
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/TestRunner.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner;
2 |
3 | /**
4 | * @author liubingmx@163.com
5 | * @create 2024/01/07
6 | */
7 | public interface TestRunner {
8 |
9 | /**
10 | * run test case
11 | * @param clazz run class
12 | * @param method run method
13 | */
14 | void run(Class> clazz, String method);
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/junit/JunitRunner.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner.junit;
2 |
3 | import cn.net.fasttest.runner.TestRunner;
4 | import org.junit.platform.engine.discovery.DiscoverySelectors;
5 | import org.junit.platform.launcher.Launcher;
6 | import org.junit.platform.launcher.LauncherDiscoveryRequest;
7 | import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
8 | import org.junit.platform.launcher.core.LauncherFactory;
9 | import org.junit.platform.launcher.listeners.TestExecutionSummary;
10 |
11 | import java.io.PrintWriter;
12 |
13 | /**
14 | * @author liubingmx@163.com
15 | * @create 2024/01/07
16 | */
17 | public class JunitRunner implements TestRunner {
18 |
19 | @Override
20 | public void run(Class> clazz, String method) {
21 | Launcher launcher = LauncherFactory.create();
22 | LauncherDiscoveryRequest request = null;
23 | if (method != null) {
24 | request = LauncherDiscoveryRequestBuilder.request()
25 | .selectors(DiscoverySelectors.selectMethod(clazz, method))
26 | .build();
27 | } else {
28 | request = LauncherDiscoveryRequestBuilder.request()
29 | .selectors(DiscoverySelectors.selectClass(clazz))
30 | .build();
31 | }
32 | JunitTestExecutionListener junitTestExecutionListener = new JunitTestExecutionListener(clazz, method);
33 | launcher.registerTestExecutionListeners(junitTestExecutionListener);
34 | launcher.execute(request);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/junit/JunitTestExecutionListener.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner.junit;
2 |
3 | import cn.net.fasttest.event.EventBus;
4 | import cn.net.fasttest.event.EventEnum;
5 | import cn.net.fasttest.event.FastSpringTestEvent;
6 | import cn.net.fasttest.runner.TestRunResult;
7 | import org.junit.platform.engine.TestExecutionResult;
8 | import org.junit.platform.launcher.TestExecutionListener;
9 | import org.junit.platform.launcher.TestIdentifier;
10 | import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
11 | import org.junit.platform.launcher.listeners.TestExecutionSummary;
12 |
13 | import java.io.PrintWriter;
14 | import java.util.Optional;
15 |
16 | /**
17 | * @author liubingmx@163.com
18 | * @create 2024/01/12
19 | */
20 | public class JunitTestExecutionListener extends SummaryGeneratingListener implements TestExecutionListener {
21 |
22 | private Class> clazz;
23 |
24 | private String method;
25 |
26 | public JunitTestExecutionListener(Class> clazz, String method) {
27 | this.clazz = clazz;
28 | this.method = method;
29 | }
30 |
31 | @Override
32 | public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
33 | super.executionFinished(testIdentifier, testExecutionResult);
34 | if (!testIdentifier.isTest()) {
35 | return;
36 | }
37 | TestExecutionSummary summary = getSummary();
38 | Optional throwable = testExecutionResult.getThrowable();
39 | TestRunResult testRunResult = new TestRunResult();
40 | testRunResult.setState(testExecutionResult.getStatus().name());
41 | testRunResult.setDisplayName(testIdentifier.getDisplayName());
42 | testRunResult.setUniqueId(method != null ? clazz.getName() + "#" + method : clazz.getName());
43 | testRunResult.setThrowable(throwable.orElse(null));
44 | testRunResult.setCost(System.currentTimeMillis() - summary.getTimeStarted());
45 | testRunResult.setFailed(summary.getTestsFailedCount());
46 | testRunResult.setSucceeded(summary.getTestsSucceededCount());
47 | testRunResult.setSkipped(summary.getTestsSkippedCount());
48 | testRunResult.setStarted(summary.getTestsStartedCount());
49 | testRunResult.setTotalTestCount(summary.getTestsFoundCount());
50 | EventBus.publishEvent(new FastSpringTestEvent(EventEnum.RUN_TESTCASE, testRunResult));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/testng/TestNGListener.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner.testng;
2 |
3 | import cn.net.fasttest.event.EventBus;
4 | import cn.net.fasttest.event.EventEnum;
5 | import cn.net.fasttest.event.FastSpringTestEvent;
6 | import cn.net.fasttest.runner.TestRunResult;
7 | import org.junit.platform.engine.TestExecutionResult;
8 | import org.testng.*;
9 |
10 | import java.util.Map;
11 | import java.util.Set;
12 |
13 | /**
14 | * @author bing
15 | * @create 2024/01/21
16 | */
17 | public class TestNGListener implements ISuiteListener {
18 |
19 | private Class> clazz;
20 |
21 | private String method;
22 |
23 | public TestNGListener(Class> clazz, String method) {
24 | this.clazz = clazz;
25 | this.method = method;
26 | }
27 |
28 | @Override
29 | public void onFinish(ISuite suite) {
30 | Map results = suite.getResults();
31 | ISuiteResult iSuiteResult = suite.getResults().get(this.method);
32 | ITestContext testContext = iSuiteResult.getTestContext();
33 | IResultMap failedTests = testContext.getFailedTests();
34 | Set allResults = failedTests.getAllResults();
35 | Throwable throwable = null;
36 | for (ITestResult allResult : allResults) {
37 | throwable = allResult.getThrowable();
38 | }
39 |
40 | TestRunResult testRunResult = new TestRunResult();
41 | testRunResult.setState(testContext.getFailedTests().size() != 0 ? TestExecutionResult.Status.FAILED.name() : TestExecutionResult.Status.SUCCESSFUL.name());
42 |
43 | testRunResult.setDisplayName(method);
44 | testRunResult.setUniqueId(clazz.getName() + "#" + method);
45 | testRunResult.setThrowable(throwable);
46 | testRunResult.setCost(testContext.getEndDate().getTime() - testContext.getStartDate().getTime());
47 | testRunResult.setFailed(testContext.getFailedTests().size());
48 | testRunResult.setSucceeded(testContext.getPassedTests().size());
49 | testRunResult.setSkipped(testContext.getSkippedTests().size());
50 | testRunResult.setStarted(results.size());
51 | EventBus.publishEvent(new FastSpringTestEvent(EventEnum.RUN_TESTCASE, testRunResult));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/runner/testng/TestNGRunner.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner.testng;
2 |
3 | import cn.net.fasttest.runner.TestRunner;
4 | import org.testng.TestNG;
5 | import org.testng.xml.XmlClass;
6 | import org.testng.xml.XmlInclude;
7 | import org.testng.xml.XmlSuite;
8 | import org.testng.xml.XmlTest;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * @author bing
15 | * @create 2024/01/21
16 | */
17 | public class TestNGRunner implements TestRunner {
18 |
19 | @Override
20 | public void run(Class> clazz, String method) {
21 | XmlClass xmlClass = new XmlClass(clazz);
22 | // now mention the methods to be included. You may use setExcludedMethods depending on the requirement.
23 | XmlInclude methodIn = new XmlInclude(method);
24 | List list = new ArrayList<>();
25 | list.add(methodIn);
26 | xmlClass.setIncludedMethods(list);
27 | XmlSuite suite = new XmlSuite();
28 | suite.setName(method);
29 |
30 | XmlTest test = new XmlTest(suite);
31 | // internally, the test method is also added to the suite object
32 | test.setName(method);
33 | List clazzList = new ArrayList<>();
34 | clazzList.add(xmlClass);
35 | test.setXmlClasses(clazzList);
36 |
37 | TestNG t = new TestNG();
38 | List suiteList = new ArrayList<>();
39 | suiteList.add(suite);
40 | t.setVerbose(0);
41 | t.setXmlSuites(suiteList);
42 | t.addListener(new TestNGListener(clazz, method));
43 | t.run();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/cn/net/fasttest/utils/FontColorUtil.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.utils;
2 |
3 | import java.util.Objects;
4 |
5 | /**
6 | * @author bing
7 | * @create 2024/01/14
8 | */
9 | public class FontColorUtil {
10 |
11 | private static final String RESET = "\033[0m";
12 | public static String BULE = "\033[1;34m";
13 | public static String RED = "\033[1;31m";
14 |
15 |
16 | public static String format(String content, String color) {
17 | if (Objects.isNull(color)) {
18 | return content;
19 | }
20 | return color + content + RESET;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/FastSpringTests.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest;
2 |
3 | import cn.net.fasttest.configuration.Configuration;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | /**
8 | * @author liubingmx@163.com
9 | * @create 2024/01/07
10 | */
11 | public class FastSpringTests {
12 |
13 | @Test
14 | public void test() {
15 |
16 | System.out.println("test...");
17 | Assertions.assertTrue(true);
18 | }
19 |
20 | @Test
21 | public void testException() {
22 | System.out.println("test...");
23 | Assertions.assertTrue(false);
24 | }
25 |
26 | public static void main(String[] args) {
27 | Configuration configuration = Configuration.ConfigurationBuilder.builder()
28 | .prompt("fast-spring-test-demo => ")
29 | .build();
30 | FastSpringTest.run(configuration);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/command/CommandHandlerTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | import cn.net.fasttest.command.handler.HelpCommandHandler;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | /**
8 | * @author bing
9 | * @create 2024/01/23
10 | */
11 | public class CommandHandlerTest {
12 |
13 |
14 | @Test
15 | public void testFactory() {
16 | CommandHandlerFactory.init();
17 | CommandHandler run = CommandHandlerFactory.getCommandHandler("run");
18 | Assertions.assertEquals(run.getCommand().getName(), "run");
19 |
20 | HelpCommandHandler helpCommandHandler = new HelpCommandHandler();
21 | CommandHandlerFactory.register(helpCommandHandler);
22 | CommandHandler commandHandler = CommandHandlerFactory.getCommandHandler(helpCommandHandler.getCommand().getName());
23 | Assertions.assertEquals(helpCommandHandler.getCommand().getName(), commandHandler.getCommand().getName());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/command/CommandParserTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.command;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | /**
7 | * @author liubingmx@163.com
8 | * @create 2024/01/11
9 | */
10 | public class CommandParserTest {
11 |
12 | @Test
13 | public void parseCommandTest() {
14 | String line = "run com.fast.spring.test.command.CommandParserTest.test";
15 | Command command = new CommandParser().parseCommand(line);
16 | Assertions.assertEquals("run", command.getName());
17 |
18 | line = "com.fast.spring.test.command.CommandParserTest.test";
19 | command = new CommandParser().parseCommand(line);
20 | Assertions.assertEquals("run", command.getName());
21 |
22 | line = "1";
23 | command = new CommandParser().parseCommand(line);
24 | Assertions.assertEquals("run", command.getName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/event/EventTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.event;
2 |
3 | import cn.net.fasttest.command.Command;
4 | import cn.net.fasttest.command.CommandParser;
5 | import cn.net.fasttest.command.handler.HistoryCommandHandler;
6 | import org.jline.reader.LineReader;
7 | import org.jline.reader.LineReaderBuilder;
8 | import org.jline.reader.impl.DefaultHighlighter;
9 | import org.jline.reader.impl.history.DefaultHistory;
10 | import org.jline.terminal.Terminal;
11 | import org.jline.terminal.TerminalBuilder;
12 | import org.junit.jupiter.api.Test;
13 |
14 | import java.io.IOException;
15 |
16 | /**
17 | * @author bing
18 | * @create 2024/01/23
19 | */
20 | public class EventTest {
21 |
22 | @Test
23 | public void testEvent() throws IOException {
24 | Terminal terminal = TerminalBuilder.builder().build();
25 | LineReader lineReader = LineReaderBuilder.builder()
26 | .terminal(terminal)
27 | .history(new DefaultHistory())
28 | .highlighter(new DefaultHighlighter())
29 | .parser(new CommandParser())
30 | .build();
31 | HistoryCommandHandler listener = new HistoryCommandHandler();
32 | EventBus.addListener(listener);
33 | FastSpringTestEvent fastSpringTestEvent = new FastSpringTestEvent(EventEnum.STARTED, lineReader);
34 | EventBus.publishEvent(fastSpringTestEvent);
35 | listener.run(new Command("history", ""));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/runner/JunitRunnerTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner;
2 |
3 | import cn.net.fasttest.runner.junit.JunitRunner;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | /**
8 | * @author bing
9 | * @create 2024/01/20
10 | */
11 | public class JunitRunnerTest {
12 |
13 | @Test
14 | public void emptyTest() {
15 | System.out.println("empty test ...");
16 | Assertions.assertTrue(true);
17 | }
18 |
19 | @Test
20 | public void testRun() {
21 | new JunitRunner().run(this.getClass(), "emptyTest");
22 | Assertions.assertTrue(true);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/cn/net/fasttest/runner/TestNGRunnerTest.java:
--------------------------------------------------------------------------------
1 | package cn.net.fasttest.runner;
2 |
3 | import cn.net.fasttest.runner.testng.TestNGRunner;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.testng.annotations.Test;
6 |
7 | /**
8 | * @author bing
9 | * @create 2024/01/21
10 | */
11 | public class TestNGRunnerTest {
12 |
13 | @Test
14 | public void emptyTest() {
15 | System.out.println("empty test ...");
16 | Assertions.assertTrue(true);
17 | }
18 |
19 | @Test
20 | public void testRun() {
21 | new TestNGRunner().run(this.getClass(), "emptyTest");
22 | Assertions.assertTrue(true);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------