├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── src ├── main │ ├── java │ │ ├── com │ │ │ └── autotest │ │ │ │ ├── Main.java │ │ │ │ ├── annotation │ │ │ │ ├── AutoTest.java │ │ │ │ └── MyMapper.java │ │ │ │ ├── base │ │ │ │ ├── AutoTestBase.java │ │ │ │ └── SpringBootTestBase.java │ │ │ │ ├── config │ │ │ │ ├── DefaultDataSourceConfig.java │ │ │ │ ├── DruidBaseConfig.java │ │ │ │ └── SchoolDataSourceConfig.java │ │ │ │ ├── extension │ │ │ │ ├── AutoTestExtension.java │ │ │ │ ├── AutoTestInvocationContext.java │ │ │ │ ├── AutoTestNameFormatter.java │ │ │ │ ├── AutoTestParameterProvider.java │ │ │ │ ├── AutoTestParameterResolver.java │ │ │ │ ├── DataDeal.java │ │ │ │ └── Parame.java │ │ │ │ ├── generate │ │ │ │ ├── ApiParameter.java │ │ │ │ ├── GenerateBase.java │ │ │ │ ├── GenerateBaseFile.java │ │ │ │ ├── GenerateFacadeCase.java │ │ │ │ └── Param.java │ │ │ │ ├── mybatis │ │ │ │ ├── AutoTestMyBatisGenerator.java │ │ │ │ ├── Dalgen.java │ │ │ │ ├── DefaultCommentGenerator.java │ │ │ │ ├── MapperConfigPlugin.java │ │ │ │ ├── MultiBeanNameGenerator.java │ │ │ │ ├── RenameExampleClassPlugin.java │ │ │ │ └── ToStringPlugin.java │ │ │ │ └── utils │ │ │ │ ├── HttpClient.java │ │ │ │ ├── ProcessObject.java │ │ │ │ ├── PropertyUtil.java │ │ │ │ └── StringUtils.java │ │ └── dal │ │ │ ├── dao │ │ │ └── school │ │ │ │ └── StudentDAO.java │ │ │ └── model │ │ │ └── school │ │ │ ├── StudentDO.java │ │ │ └── StudentDOExample.java │ └── resources │ │ ├── application.yml │ │ ├── dal │ │ └── mapping │ │ │ └── school │ │ │ └── StudentMapper.xml │ │ ├── ftl │ │ ├── generateDataSourceConfig.ftl │ │ ├── generateFacadeCase.ftl │ │ └── generateTestBase.ftl │ │ ├── lib │ │ └── mysql-connector-java-5.1.30.jar │ │ ├── logback.xml │ │ └── webdriver │ │ └── chromedriver.exe └── test │ ├── java │ └── com │ │ └── autotest │ │ ├── Generator.java │ │ ├── example │ │ ├── QueryOrder.java │ │ ├── QueryUserFacade.java │ │ └── UserResult.java │ │ ├── test │ │ ├── HttpTest.java │ │ ├── MybatisTest.java │ │ ├── QueryUserFacadeQueryUserByIdTest.java │ │ └── WebTest.java │ │ └── testbase │ │ ├── SchoolTestBase.java │ │ └── web │ │ └── WebTestBase.java │ └── resources │ └── autotest │ ├── csvTest.csv │ ├── httpTest.csv │ ├── mybatisTest.csv │ └── test │ └── queryUserFacadeQueryUserByIdTestSuccess.csv └── student.sql /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | _site 6 | *.iml 7 | .idea/ 8 | target/ 9 | *.log 10 | out/ 11 | 12 | *.pydevproject 13 | .project 14 | .metadata 15 | bin/ 16 | tmp/ 17 | *.tmp 18 | *.bak 19 | *.swp 20 | *~.nib 21 | .classpath 22 | .settings/ 23 | .loadpath 24 | 25 | # External tool builders 26 | .externalToolBuilders/ 27 | 28 | # Locally stored "Eclipse launch configurations" 29 | *.launch 30 | 31 | # CDT-specific 32 | .cproject 33 | 34 | # PDT-specific 35 | .buildpath 36 | 37 | 38 | ################# 39 | ## Visual Studio 40 | ################# 41 | 42 | ## Ignore Visual Studio temporary files, build results, and 43 | ## files generated by popular Visual Studio add-ons. 44 | 45 | # User-specific files 46 | *.suo 47 | *.user 48 | *.sln.docstates 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | *_i.c 54 | *_p.c 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.vspscc 68 | .builds 69 | *.dotCover 70 | 71 | #packages/ 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | 80 | # Visual Studio profiler 81 | *.psess 82 | *.vsp 83 | 84 | # ReSharper is a .NET coding add-in 85 | _ReSharper* 86 | 87 | # Installshield output folder 88 | [Ee]xpress 89 | 90 | # DocProject is a documentation generator add-in 91 | DocProject/buildhelp/ 92 | DocProject/Help/*.HxT 93 | DocProject/Help/*.HxC 94 | DocProject/Help/*.hhc 95 | DocProject/Help/*.hhk 96 | DocProject/Help/*.hhp 97 | DocProject/Help/Html2 98 | DocProject/Help/html 99 | 100 | # Click-Once directory 101 | publish 102 | 103 | # Others 104 | [Bb]in 105 | [Oo]bj 106 | sql 107 | TestResults 108 | *.Cache 109 | ClientBin 110 | stylecop.* 111 | ~$* 112 | *.dbmdl 113 | Generated_Code #added for RIA/Silverlight projects 114 | 115 | # Backup & report files from converting an old project file to a newer 116 | # Visual Studio version. Backup files are not needed, because we have git ;-) 117 | _UpgradeReport_Files/ 118 | Backup*/ 119 | UpgradeLog*.XML 120 | 121 | 122 | 123 | ############ 124 | ## Windows 125 | ############ 126 | 127 | # Windows image file caches 128 | Thumbs.db 129 | 130 | # Folder config file 131 | Desktop.ini 132 | 133 | 134 | ############# 135 | ## Python 136 | ############# 137 | 138 | *.py[co] 139 | 140 | # Packages 141 | *.egg 142 | *.egg-info 143 | dist 144 | build 145 | eggs 146 | parts 147 | bin 148 | var 149 | sdist 150 | develop-eggs 151 | .installed.cfg 152 | 153 | # Installer logs 154 | pip-log.txt 155 | 156 | # Unit test / coverage reports 157 | .coverage 158 | .tox 159 | 160 | #Translations 161 | *.mo 162 | 163 | #Mr Developer 164 | .mr.developer.cfg 165 | 166 | # Mac crap 167 | .DS_Store 168 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 ychaoyang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 新特性: 2 | ========== 3 | 1.自动生成测试用例 4 | 5 | 2.测试代码更简洁,全程都是对象传递 6 | 7 | 3.数据准备更方便,可根据需要自动生成csv 8 | 9 | 4.数据验证更容易,直接断言数据库对象 10 | 11 | 5.配置文件更简单,只需一个数据库连接配置 12 | 13 | 14 | 使用前 15 | ====== 16 | 因为JUnit 5仅支持jdk1.8及以上,所以需要先安装jdk1.8,安装教程请自行百度。 17 | 18 | IDE方面,Intellij IDEA2016.2开始对 JUnit 5支持 ,下载最新版本即可。 19 | 20 | 使用说明 21 | ======== 22 | JUnit 5仍然支持对@Test 标记测试方法,但若要使用@AutoTest,需要测试方法至少有一个参数,并且file的值不为空。 23 | 24 | 示例: 25 | ~~~ 26 | @AutoTest(file = "/autotest/simpleTest.csv") 27 | 28 | void simpleTest(int testId, User user) { 29 | 30 | System.out.println("这是第 " + testId + " 条测试用例"); 31 | 32 | System.out.println(user.getName()); 33 | 34 | } 35 | ~~~ 36 | simpleTest.csv文件的内容: 37 | ~~~ 38 | name,age,testId 39 | 40 | Lili,18,1001 41 | 42 | Zhangsan,19,1002 43 | ~~~ 44 | csv文件第一行是参数名,参数名之间以英文逗号,隔开 45 | 46 | csv文件第二行开始是参数值,与第一行参数名一一对应,从第二行开始,有几行则执行几次测试方法。 47 | 48 | 运行上面的测试方法后,结果如下: 49 | ~~~ 50 | 这是第 1001 条测试用例 51 | 52 | Lili 53 | 54 | 这是第 1002 条测试用例 55 | 56 | Zhangsan 57 | ~~~ 58 | 生成CSV文件 59 | ~~~ 60 | 运行测试用例时,若没有找到csv文件则会生成对应的文件,如存在则不会生成 61 | ~~~ 62 | 生成数据库操作类 63 | ~~~ 64 | 在AutoTest注解中添加project,值填项目名(与数据库名相同),运行用例时则会自动生成数据库操作类,生成完成后去掉project 65 | 66 | @AutoTest(file = "/autotest/simpleTest.csv" , project = "school") 67 | ~~~ 68 | 69 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.autotest 8 | autotest-parent 9 | 1.0 10 | jar 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 2.0.1.RELEASE 15 | 16 | 17 | 18 | 19 | UTF-8 20 | 1.8 21 | 5.2.0 22 | 5.2.0 23 | 1.2.0 24 | 3.18.2-GA 25 | 1.7.12 26 | 2.7.0 27 | 1.1.2 28 | 3.7.1 29 | 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-web 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-data-redis 51 | 52 | 53 | 54 | org.mybatis.spring.boot 55 | mybatis-spring-boot-starter 56 | 1.3.1 57 | 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-configuration-processor 62 | true 63 | 64 | 65 | 66 | mysql 67 | mysql-connector-java 68 | 69 | 70 | 71 | org.javassist 72 | javassist 73 | ${javassist.version} 74 | 75 | 76 | 77 | org.slf4j 78 | slf4j-api 79 | 1.7.7 80 | 81 | 82 | org.slf4j 83 | log4j-over-slf4j 84 | 1.7.7 85 | 86 | 87 | 88 | 89 | org.junit.jupiter 90 | junit-jupiter-api 91 | ${junit.jupiter.version} 92 | 93 | 94 | org.junit.jupiter 95 | junit-jupiter-params 96 | ${junit.jupiter.version} 97 | 98 | 99 | org.junit.jupiter 100 | junit-jupiter-engine 101 | ${junit.jupiter.version} 102 | 103 | 104 | org.junit.platform 105 | junit-platform-runner 106 | ${junit.platform.version} 107 | 108 | 109 | 110 | 111 | com.univocity 112 | univocity-parsers 113 | 2.4.1 114 | 115 | 116 | 117 | com.alibaba 118 | fastjson 119 | 1.2.31 120 | 121 | 122 | 123 | com.alibaba 124 | druid 125 | ${druid.version} 126 | 127 | 128 | 129 | 130 | javax 131 | javaee-api 132 | 7.0 133 | 134 | 135 | 136 | 137 | org.seleniumhq.selenium 138 | selenium-server 139 | ${webdriver.version} 140 | 141 | 142 | 143 | com.codeborne 144 | selenide 145 | 4.12.0 146 | 147 | 148 | org.seleniumhq.selenium 149 | selenium-java 150 | 151 | 152 | org.seleniumhq.selenium 153 | selenium-api 154 | 155 | 156 | 157 | 158 | 159 | net.sourceforge.javacsv 160 | javacsv 161 | 2.0 162 | 163 | 164 | 165 | org.apache.httpcomponents 166 | httpclient 167 | 4.3.6 168 | 169 | 170 | 171 | org.mybatis.generator 172 | mybatis-generator-core 173 | 1.3.5 174 | 175 | 176 | 177 | org.freemarker 178 | freemarker 179 | 2.3.27-incubating 180 | 181 | 182 | 183 | net.sourceforge.tess4j 184 | tess4j 185 | 3.3.0 186 | 187 | 188 | com.sun.jna 189 | jna 190 | 191 | 192 | 193 | 194 | 195 | dom4j 196 | dom4j 197 | 1.6.1 198 | 199 | 200 | xml-apis 201 | xml-apis 202 | 203 | 204 | 205 | 206 | 207 | org.apiguardian 208 | apiguardian-api 209 | 1.0.0 210 | 211 | 212 | 213 | tk.mybatis 214 | mapper-spring-boot-starter 215 | 1.2.1 216 | 217 | 218 | 219 | org.yaml 220 | snakeyaml 221 | 1.19 222 | 223 | 224 | 225 | 226 | 227 | com.alibaba 228 | dubbo 229 | 2.6.2 230 | 231 | 232 | spring 233 | org.springframework 234 | 235 | 236 | log4j 237 | log4j 238 | 239 | 240 | 241 | 242 | io.dubbo.springboot 243 | spring-boot-starter-dubbo 244 | 1.0.0 245 | 246 | 247 | 248 | 249 | org.apache.curator 250 | curator-framework 251 | 4.0.0 252 | 253 | 254 | com.esotericsoftware.kryo 255 | kryo 256 | 2.24.0 257 | 258 | 259 | de.javakaffee 260 | kryo-serializers 261 | 0.26 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | src/main/resources 271 | 272 | 273 | src/test/resources 274 | 275 | 276 | src/main/java 277 | 278 | 279 | src/test/java 280 | 281 | 282 | 283 | 284 | org.springframework.boot 285 | spring-boot-maven-plugin 286 | 287 | 288 | org.codehaus.mojo 289 | build-helper-maven-plugin 290 | 1.10 291 | 292 | 293 | add-source 294 | generate-sources 295 | 296 | add-source 297 | 298 | 299 | 300 | src/test/java 301 | 302 | 303 | 304 | 305 | 306 | 307 | maven-compiler-plugin 308 | 3.7.0 309 | 310 | ${java.version} 311 | ${java.version} 312 | ${project.build.sourceEncoding} 313 | 314 | 315 | 316 | org.apache.maven.plugins 317 | maven-surefire-plugin 318 | 2.21.0 319 | 320 | 321 | **/*Test.java 322 | 323 | 324 | fast 325 | slow 326 | 327 | once 328 | -Dfile.encoding=UTF-8 329 | 1 330 | 331 | 332 | 333 | org.junit.platform 334 | junit-platform-surefire-provider 335 | ${junit.platform.version} 336 | 337 | 338 | org.junit.jupiter 339 | junit-jupiter-engine 340 | ${junit.jupiter.version} 341 | 342 | 343 | org.aspectj 344 | aspectjweaver 345 | ${aspectj.version} 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | nexus-aliyun 354 | Nexus aliyun 355 | http://maven.aliyun.com/nexus/content/groups/public 356 | default 357 | 358 | true 359 | 360 | 361 | false 362 | 363 | 364 | 365 | 366 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/Main.java: -------------------------------------------------------------------------------- 1 | package com.autotest; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | 7 | 8 | @SpringBootApplication 9 | public class Main { 10 | public static void main(String[] args) { 11 | ConfigurableApplicationContext run = SpringApplication.run(Main.class, args); 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/annotation/AutoTest.java: -------------------------------------------------------------------------------- 1 | package com.autotest.annotation; 2 | 3 | import com.autotest.extension.AutoTestExtension; 4 | import com.autotest.extension.AutoTestParameterProvider; 5 | import org.junit.jupiter.api.TestTemplate; 6 | import org.junit.jupiter.api.extension.ExtendWith; 7 | import org.junit.jupiter.params.provider.ArgumentsSource; 8 | 9 | import java.lang.annotation.*; 10 | 11 | 12 | /** 13 | * Created by huairen on 2017/7/13. 14 | */ 15 | @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD}) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Documented 18 | @TestTemplate 19 | @ExtendWith(AutoTestExtension.class) 20 | @ArgumentsSource(AutoTestParameterProvider.class) 21 | public @interface AutoTest { 22 | 23 | String name() default "[{index}] {arguments}"; 24 | 25 | String file(); 26 | 27 | String encoding() default "UTF-8"; 28 | 29 | /**根据项目名称生成base类*/ 30 | String project() default ""; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/annotation/MyMapper.java: -------------------------------------------------------------------------------- 1 | package com.autotest.annotation; 2 | 3 | import tk.mybatis.mapper.common.Mapper; 4 | import tk.mybatis.mapper.common.MySqlMapper; 5 | 6 | /** 7 | * Created by yu on 17/12/6. 8 | */ 9 | public interface MyMapper extends Mapper, MySqlMapper { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/base/AutoTestBase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.base; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | import java.io.File; 9 | import java.net.URL; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by huairen on 2017/7/20. 14 | */ 15 | 16 | public class AutoTestBase { 17 | 18 | protected final Logger logger = LoggerFactory.getLogger(AutoTestBase.class); 19 | 20 | protected RestTemplate restTemplate = new RestTemplate(); 21 | 22 | /** 23 | * 暂停*秒 24 | * 25 | * @param time 26 | */ 27 | protected static void sleep(int time) { 28 | try { 29 | Thread.sleep(time * 1000); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | 36 | 37 | 38 | protected void assertEquals(Object expected, Object actual) { 39 | Assertions.assertEquals(expected, actual); 40 | } 41 | 42 | protected void assertNotEquals(Object expected, Object actual) { 43 | Assertions.assertNotEquals(expected, actual); 44 | } 45 | 46 | protected void assertTrue(boolean condition) { 47 | Assertions.assertTrue(condition); 48 | } 49 | 50 | protected void assertFalse(boolean condition) { 51 | Assertions.assertFalse(condition); 52 | } 53 | 54 | protected void assertNull(Object actual) { 55 | Assertions.assertNull(actual); 56 | } 57 | 58 | protected void assertNotNull(Object actual) { 59 | Assertions.assertNotNull(actual); 60 | } 61 | 62 | 63 | /** 64 | * 首字母转小写 65 | * 66 | * @param s 67 | * @return 68 | */ 69 | protected String toLowerCaseFirstOne(String s) { 70 | if (Character.isLowerCase(s.charAt(0))) { 71 | return s; 72 | } else { 73 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 74 | } 75 | } 76 | 77 | /** 78 | * 首字母转大写 79 | * 80 | * @param s 81 | * @return 82 | */ 83 | protected String toUpperCaseFirstOne(String s) { 84 | if (Character.isUpperCase(s.charAt(0))) { 85 | return s; 86 | } else { 87 | return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString(); 88 | } 89 | } 90 | 91 | /** 92 | * 得到当前类的路径 93 | * 94 | * @param clazz 95 | * @return 96 | */ 97 | protected String getClassFilePath(Class clazz) { 98 | try { 99 | return java.net.URLDecoder.decode(getClassFile(clazz).getAbsolutePath(), "UTF-8"); 100 | } catch (Exception e) { 101 | e.printStackTrace(); 102 | return ""; 103 | } 104 | } 105 | 106 | /** 107 | * 取得当前类所在的文件 108 | * 109 | * @param clazz 110 | * @return 111 | */ 112 | protected File getClassFile(Class clazz) { 113 | URL path = clazz.getResource(clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1) + ".classs"); 114 | if (path == null) { 115 | String name = clazz.getName().replaceAll("[.]", "/"); 116 | path = clazz.getResource("/" + name + ".class"); 117 | } 118 | return new File(path.getFile()); 119 | } 120 | 121 | protected void print(Object object) { 122 | String str = ""; 123 | if (object instanceof List) { 124 | logger.info("========================================"); 125 | List list = (List) object; 126 | logger.info("List size:" + list.size()); 127 | for (int i = 0; i < list.size(); i++) { 128 | 129 | str = list.get(i).toString(); 130 | logger.info(str); 131 | } 132 | logger.info("========================================"); 133 | return; 134 | } else if (object == null) { 135 | 136 | str = "null"; 137 | } else { 138 | str = object.toString(); 139 | } 140 | 141 | logger.info("========================================"); 142 | logger.info(str); 143 | logger.info("========================================"); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/base/SpringBootTestBase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.base; 2 | 3 | import com.autotest.Main; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit.jupiter.SpringExtension; 7 | 8 | /** 9 | * @author huairen 10 | * Created on 18/3/8. 11 | */ 12 | @SpringBootTest( 13 | classes = Main.class, 14 | webEnvironment = SpringBootTest.WebEnvironment.NONE 15 | ) 16 | @ExtendWith(SpringExtension.class) 17 | public class SpringBootTestBase extends AutoTestBase { 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/config/DefaultDataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.autotest.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.mybatis.spring.SqlSessionFactoryBean; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 12 | 13 | import javax.sql.DataSource; 14 | 15 | /** 16 | * Created by huairen on 2017/12/11. 17 | */ 18 | @Configuration 19 | //@MapperScan(basePackages = "dal.dao.default", sqlSessionFactoryRef = "defaultSqlSessionFactory", nameGenerator = 20 | // MultiBeanNameGenerator.class) 21 | public class DefaultDataSourceConfig extends DruidBaseConfig { 22 | 23 | @Value("${ds.default.url}") 24 | private String url; 25 | 26 | @Value("${ds.default.username}") 27 | private String username; 28 | 29 | @Value("${ds.default.password}") 30 | private String password; 31 | 32 | @Value("${ds.default.driverClassName}") 33 | private String driverClassName; 34 | 35 | @Bean(name = "defaultDataSource") 36 | @Primary 37 | public DataSource defaultDataSource() { 38 | DruidDataSource dataSource = new DruidDataSource(); 39 | return setDataSource(dataSource, url, username, password, driverClassName); 40 | } 41 | 42 | @Bean(name = "defaultTransactionManager") 43 | @Primary 44 | public DataSourceTransactionManager defaultTransactionManager() { 45 | return new DataSourceTransactionManager(defaultDataSource()); 46 | } 47 | 48 | @Bean(name = "defaultSqlSessionFactory") 49 | @Primary 50 | public SqlSessionFactory defaultSqlSessionFactory(@Qualifier("defaultDataSource") DataSource defaultDataSource) 51 | throws Exception { 52 | final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 53 | sessionFactory.setDataSource(defaultDataSource); 54 | return sessionFactory.getObject(); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/config/DruidBaseConfig.java: -------------------------------------------------------------------------------- 1 | package com.autotest.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * Created by yu on 17/12/5. 9 | */ 10 | @Configuration 11 | public class DruidBaseConfig { 12 | 13 | 14 | /** 15 | * setDataSource 16 | * @param dataSource 17 | * @param url 18 | * @param username 19 | * @param password 20 | * @param driverClassName 21 | * @return 22 | */ 23 | protected DruidDataSource setDataSource(DruidDataSource dataSource, String url, String username, String password, 24 | String driverClassName) { 25 | dataSource.setUrl(url); 26 | dataSource.setUsername(username); 27 | dataSource.setPassword(password); 28 | dataSource.setDriverClassName(driverClassName); 29 | //configuration 30 | dataSource.setInitialSize(10); 31 | dataSource.setMinIdle(1); 32 | dataSource.setMaxActive(500); 33 | dataSource.setMaxWait(6000); 34 | dataSource.setTimeBetweenEvictionRunsMillis(60000); 35 | dataSource.setMinEvictableIdleTimeMillis(300000); 36 | dataSource.setValidationQuery("SELECT 1 FROM DUAL"); 37 | dataSource.setTestWhileIdle(true); 38 | dataSource.setTestOnBorrow(false); 39 | dataSource.setTestOnReturn(false); 40 | dataSource.setPoolPreparedStatements(false); 41 | dataSource.setMaxPoolPreparedStatementPerConnectionSize(20); 42 | return dataSource; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/config/SchoolDataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.autotest.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.autotest.mybatis.MultiBeanNameGenerator; 5 | import org.apache.ibatis.session.SqlSessionFactory; 6 | import org.mybatis.spring.SqlSessionFactoryBean; 7 | import tk.mybatis.spring.annotation.MapperScan; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 13 | import javax.sql.DataSource; 14 | 15 | @Configuration 16 | @MapperScan(basePackages = "dal.dao.school", sqlSessionFactoryRef = "schoolSqlSessionFactory", nameGenerator = 17 | MultiBeanNameGenerator.class) 18 | public class SchoolDataSourceConfig extends DruidBaseConfig { 19 | 20 | @Value("${ds.school.url}") 21 | private String url; 22 | 23 | @Value("${ds.school.username}") 24 | private String username; 25 | 26 | @Value("${ds.school.password}") 27 | private String password; 28 | 29 | @Value("${ds.school.driverClassName}") 30 | private String driverClassName; 31 | 32 | @Bean(name = "schoolDataSource") 33 | public DataSource schoolDataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | return setDataSource(dataSource, url, username, password, driverClassName); 36 | } 37 | 38 | @Bean(name = "schoolTransactionManager") 39 | public DataSourceTransactionManager schoolTransactionManager() { 40 | return new DataSourceTransactionManager(schoolDataSource()); 41 | } 42 | 43 | @Bean(name = "schoolSqlSessionFactory") 44 | public SqlSessionFactory schoolSqlSessionFactory(@Qualifier("schoolDataSource") DataSource schoolDataSource) 45 | throws Exception { 46 | final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 47 | sessionFactory.setDataSource(schoolDataSource); 48 | return sessionFactory.getObject(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/AutoTestExtension.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import com.autotest.annotation.AutoTest; 4 | import com.autotest.mybatis.Dalgen; 5 | import org.junit.jupiter.api.extension.*; 6 | import org.junit.jupiter.params.provider.Arguments; 7 | import org.junit.jupiter.params.provider.ArgumentsProvider; 8 | import org.junit.jupiter.params.provider.ArgumentsSource; 9 | import org.junit.jupiter.params.support.AnnotationConsumerInitializer; 10 | import org.junit.platform.commons.util.*; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Qualifier; 15 | import org.springframework.beans.factory.annotation.Value; 16 | import org.springframework.beans.factory.config.DependencyDescriptor; 17 | import org.springframework.boot.test.context.SpringBootTest; 18 | import org.springframework.context.ApplicationContext; 19 | import org.springframework.core.MethodParameter; 20 | import org.springframework.core.annotation.AnnotatedElementUtils; 21 | import org.springframework.core.annotation.SynthesizingMethodParameter; 22 | import org.springframework.test.context.ContextConfiguration; 23 | import org.springframework.test.context.TestContextManager; 24 | import org.springframework.util.Assert; 25 | 26 | import java.lang.annotation.Annotation; 27 | import java.lang.reflect.*; 28 | import java.util.Optional; 29 | import java.util.concurrent.atomic.AtomicLong; 30 | import java.util.stream.Stream; 31 | 32 | import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; 33 | import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; 34 | 35 | /** 36 | * Created by huairen on 2017/7/14. 37 | */ 38 | public class AutoTestExtension implements TestTemplateInvocationContextProvider, BeforeAllCallback, AfterAllCallback, 39 | TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, 40 | AfterTestExecutionCallback { 41 | protected static final Logger logger = LoggerFactory.getLogger(AutoTestExtension.class.getName()); 42 | 43 | private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create("AutoTestExtension", 44 | "DataDeal"); 45 | 46 | private int num = 0; 47 | 48 | @Override 49 | public boolean supportsTestTemplate(ExtensionContext context) { 50 | return AnnotationUtils.isAnnotated(context.getTestMethod(), AutoTest.class); 51 | } 52 | 53 | @Override 54 | public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { 55 | Method templateMethod = Preconditions.notNull(context.getTestMethod().orElse(null), 56 | "test method must not be null"); 57 | AutoTestNameFormatter formatter = createNameFormatter(templateMethod); 58 | AtomicLong invocationCount = new AtomicLong(0L); 59 | return (Stream) findRepeatableAnnotations(templateMethod, ArgumentsSource.class) 60 | .stream() 61 | .map(ArgumentsSource::value) 62 | .map(ReflectionUtils::newInstance) 63 | .map(provider -> AnnotationConsumerInitializer.initialize(templateMethod, provider)) 64 | .flatMap(provider -> arguments(provider, context)) 65 | .map(Arguments::get) 66 | .map((arguments) -> { 67 | return new AutoTestInvocationContext(formatter, arguments); 68 | }) 69 | .peek((invocationContext) -> { 70 | invocationCount.incrementAndGet(); 71 | }).onClose(() -> { 72 | Preconditions.condition(invocationCount.get() > 0L, () -> { 73 | return "当使用注解 @" + AutoTest.class.getSimpleName() + " 的时候,测试方法需要至少一个参数"; 74 | }); 75 | }); 76 | 77 | } 78 | 79 | 80 | @Override 81 | public void beforeAll(ExtensionContext context) throws Exception { 82 | if (isSpringSupport(context)) { 83 | getTestContextManager(context).beforeTestClass(); 84 | } 85 | } 86 | 87 | @Override 88 | public void afterAll(ExtensionContext context) throws Exception { 89 | if (isSpringSupport(context)) { 90 | try { 91 | getTestContextManager(context).afterTestClass(); 92 | } finally { 93 | context.getStore(NAMESPACE).remove(context.getTestClass().get()); 94 | } 95 | } 96 | } 97 | 98 | @Override 99 | public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { 100 | if (isSpringSupport(context)) { 101 | getTestContextManager(context).prepareTestInstance(testInstance); 102 | } 103 | } 104 | 105 | @Override 106 | public void beforeEach(ExtensionContext context) throws Exception { 107 | if (isSpringSupport(context)) { 108 | Object testInstance = context.getTestInstance(); 109 | Method testMethod = context.getTestMethod().get(); 110 | getTestContextManager(context).beforeTestMethod(testInstance, testMethod); 111 | } 112 | } 113 | 114 | 115 | @Override 116 | public void beforeTestExecution(ExtensionContext context) throws Exception { 117 | if (isSpringSupport(context)) { 118 | Object testInstance = context.getTestInstance(); 119 | Method testMethod = context.getTestMethod().get(); 120 | getTestContextManager(context).beforeTestExecution(testInstance, testMethod); 121 | } 122 | int times = context.getStore(NAMESPACE).get("times", int.class); 123 | String methodName = context.getStore(NAMESPACE).get("methodName", String.class); 124 | logger.info("========[{}]共执行[{}]次, 开始执行第[{}]轮========", methodName, times, num++ < times ? num : times); 125 | } 126 | 127 | @Override 128 | public void afterTestExecution(ExtensionContext context) throws Exception { 129 | if (isSpringSupport(context)) { 130 | Object testInstance = context.getTestInstance(); 131 | Method testMethod = context.getTestMethod().get(); 132 | Throwable testException = context.getExecutionException().orElse(null); 133 | getTestContextManager(context).afterTestExecution(testInstance, testMethod, testException); 134 | } 135 | } 136 | 137 | @Override 138 | public void afterEach(ExtensionContext context) throws Exception { 139 | if (isSpringSupport(context)) { 140 | Object testInstance = context.getTestInstance(); 141 | Method testMethod = context.getTestMethod().get(); 142 | Throwable testException = context.getExecutionException().orElse(null); 143 | getTestContextManager(context).afterTestMethod(testInstance, testMethod, testException); 144 | } 145 | } 146 | 147 | 148 | private AutoTestNameFormatter createNameFormatter(Method templateMethod) { 149 | AutoTest autoTest = findAnnotation(templateMethod, AutoTest.class).get(); 150 | String name = autoTest.name().trim(); 151 | if (StringUtils.isBlank(name)) { 152 | logger.warn(String.format( 153 | "Configuration error: @AutoTest on method [%s] must be declared with a non-empty name.", 154 | templateMethod)); 155 | // name = AnnotationUtils.getDefaultValue(autoTest, "name", String.class).get(); 156 | } 157 | 158 | return new AutoTestNameFormatter(name); 159 | } 160 | 161 | protected static Stream arguments(ArgumentsProvider provider, ExtensionContext context) { 162 | try { 163 | return provider.provideArguments(context); 164 | } catch (Exception e) { 165 | throw ExceptionUtils.throwAsUncheckedException(e); 166 | } 167 | } 168 | 169 | static ApplicationContext getApplicationContext(ExtensionContext context) { 170 | return getTestContextManager(context).getTestContext().getApplicationContext(); 171 | } 172 | 173 | private static TestContextManager getTestContextManager(ExtensionContext context) { 174 | Assert.notNull(context, "ExtensionContext must not be null"); 175 | Class testClass = context.getTestClass().get(); 176 | ExtensionContext.Store store = context.getStore(NAMESPACE); 177 | return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class); 178 | } 179 | 180 | static boolean isAutowirable(Parameter parameter) { 181 | return ApplicationContext.class.isAssignableFrom(parameter.getType()) 182 | || AnnotatedElementUtils.hasAnnotation(parameter, Autowired.class) 183 | || AnnotatedElementUtils.hasAnnotation(parameter, Qualifier.class) 184 | || AnnotatedElementUtils.hasAnnotation(parameter, Value.class); 185 | } 186 | 187 | static Object resolveDependency(Parameter parameter, Class containingClass, ApplicationContext 188 | applicationContext) { 189 | boolean required = findMergedAnnotation(parameter, Autowired.class).map(Autowired::required).orElse(true); 190 | MethodParameter methodParameter = SynthesizingMethodParameter.forParameter(parameter); 191 | DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required); 192 | descriptor.setContainingClass(containingClass); 193 | return applicationContext.getAutowireCapableBeanFactory().resolveDependency(descriptor, null); 194 | } 195 | 196 | private static Optional findMergedAnnotation(AnnotatedElement element, Class 197 | annotationType) { 198 | return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType)); 199 | } 200 | 201 | /** 202 | * 是否需要支持spring 203 | */ 204 | private boolean isSpringSupport(ExtensionContext context) { 205 | Class clazz = context.getTestClass().get(); 206 | boolean result = false; 207 | while (!clazz.equals(Object.class)) { 208 | boolean isContextConfiguration = false; 209 | if (clazz.isAnnotationPresent(ContextConfiguration.class) 210 | // || clazz.isAnnotationPresent(SpringBootTest.class) 211 | ) { 212 | isContextConfiguration = true; 213 | } 214 | if (isContextConfiguration) { 215 | result = true; 216 | break; 217 | } 218 | clazz = clazz.getSuperclass(); 219 | } 220 | return result; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/AutoTestInvocationContext.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import org.junit.jupiter.api.extension.Extension; 4 | import org.junit.jupiter.api.extension.TestTemplateInvocationContext; 5 | 6 | import java.util.List; 7 | 8 | import static java.util.Collections.singletonList; 9 | 10 | /** 11 | * Created by huairen on 2017/7/17. 12 | */ 13 | public class AutoTestInvocationContext implements TestTemplateInvocationContext { 14 | 15 | private final AutoTestNameFormatter formatter; 16 | private final Object[] arguments; 17 | 18 | AutoTestInvocationContext(AutoTestNameFormatter formatter, Object[] arguments) { 19 | this.formatter = formatter; 20 | this.arguments = arguments; 21 | } 22 | 23 | @Override 24 | public String getDisplayName(int invocationIndex) { 25 | return formatter.format(invocationIndex, arguments); 26 | } 27 | 28 | @Override 29 | public List getAdditionalExtensions() { 30 | return singletonList(new AutoTestParameterResolver(arguments)); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/AutoTestNameFormatter.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import org.junit.platform.commons.JUnitException; 4 | import org.junit.platform.commons.util.StringUtils; 5 | 6 | import java.text.MessageFormat; 7 | import java.util.stream.IntStream; 8 | 9 | import static java.util.stream.Collectors.joining; 10 | 11 | /** 12 | * Created by huairen on 2017/7/17. 13 | */ 14 | public class AutoTestNameFormatter { 15 | private final String namePattern; 16 | 17 | AutoTestNameFormatter(String namePattern) { 18 | this.namePattern = namePattern; 19 | } 20 | 21 | String format(int invocationIndex, Object... arguments) { 22 | String pattern = prepareMessageFormatPattern(invocationIndex, arguments); 23 | Object[] humanReadableArguments = makeReadable(arguments); 24 | return formatSafely(pattern, humanReadableArguments); 25 | } 26 | 27 | private String prepareMessageFormatPattern(int invocationIndex, Object[] arguments) { 28 | String result = namePattern.replace("{index}", String.valueOf(invocationIndex)); 29 | if (result.contains("{arguments}")) { 30 | // @formatter:off 31 | String replacement = IntStream.range(0, arguments.length) 32 | .mapToObj(index -> "{" + index + "}") 33 | .collect(joining(", ")); 34 | // @formatter:on 35 | result = result.replace("{arguments}", replacement); 36 | } 37 | return result; 38 | } 39 | 40 | private Object[] makeReadable(Object[] arguments) { 41 | // Note: humanReadableArguments must be an Object[] in order to 42 | // avoid varargs issues with non-Eclipse compilers. 43 | Object[] humanReadableArguments = new String[arguments.length]; 44 | for (int i = 0; i < arguments.length; i++) { 45 | humanReadableArguments[i] = StringUtils.nullSafeToString(arguments[i]); 46 | } 47 | return humanReadableArguments; 48 | } 49 | 50 | private String formatSafely(String pattern, Object[] arguments) { 51 | try { 52 | return MessageFormat.format(pattern, arguments); 53 | } catch (IllegalArgumentException ex) { 54 | String message = "The naming pattern defined for the parameterized tests is invalid. " 55 | + "The nested exception contains more details."; 56 | throw new JUnitException(message, ex); 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/AutoTestParameterProvider.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import com.autotest.annotation.AutoTest; 4 | import com.autotest.mybatis.Dalgen; 5 | import com.autotest.utils.ProcessObject; 6 | import com.autotest.utils.StringUtils; 7 | import org.junit.jupiter.api.extension.ExtensionContext; 8 | import org.junit.jupiter.params.provider.Arguments; 9 | import org.junit.jupiter.params.provider.ArgumentsProvider; 10 | import org.junit.jupiter.params.support.AnnotationConsumer; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.stream.Stream; 16 | 17 | /** 18 | * @author huairen 19 | * Created on 18/4/2. 20 | */ 21 | public class AutoTestParameterProvider implements ArgumentsProvider, AnnotationConsumer { 22 | 23 | private String file; 24 | private String project; 25 | private List objects; 26 | 27 | @Override 28 | public void accept(AutoTest autoTest) { 29 | this.file = autoTest.file(); 30 | this.project = autoTest.project(); 31 | this.objects = new ArrayList<>(); 32 | } 33 | 34 | 35 | @Override 36 | public Stream provideArguments(ExtensionContext context) throws Exception { 37 | //生成mybatis代码 38 | if (StringUtils.isNotBlank(this.project)) { 39 | Dalgen dalgen = new Dalgen(); 40 | dalgen.gen(this.project); 41 | } 42 | List args = DataDeal.getParams(context, this.file); 43 | for (Object ob : args) { 44 | HashMap map = (HashMap) ob; 45 | List pars = DataDeal.getVariables(context); 46 | Object[] obs = new Object[pars.size()]; 47 | for (int i = 0; i < pars.size(); i++) { 48 | Parame p = pars.get(i); 49 | Class cl = p.getType(); 50 | if (DataDeal.isJavaClass(cl) || cl.isEnum()) { 51 | obs[i] = ProcessObject.processing(cl, map.get(p.getName())); 52 | } else { 53 | obs[i] = DataDeal.mapToObject(map, cl, p.getName()); 54 | } 55 | } 56 | objects.add(obs); 57 | } 58 | return objects.stream().map(AutoTestParameterProvider::toArguments); 59 | } 60 | 61 | private static Arguments toArguments(Object item) { 62 | if (item instanceof Arguments) { 63 | return (Arguments) item; 64 | } 65 | if (item instanceof Object[]) { 66 | return Arguments.of((Object[]) item); 67 | } 68 | return Arguments.of(item); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/AutoTestParameterResolver.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import org.junit.jupiter.api.extension.ExtensionContext; 4 | import org.junit.jupiter.api.extension.ParameterContext; 5 | import org.junit.jupiter.api.extension.ParameterResolutionException; 6 | import org.junit.jupiter.api.extension.ParameterResolver; 7 | import org.junit.jupiter.params.converter.ArgumentConverter; 8 | import org.junit.jupiter.params.converter.ConvertWith; 9 | import org.junit.jupiter.params.converter.DefaultArgumentConverter; 10 | import org.junit.jupiter.params.support.AnnotationConsumerInitializer; 11 | import org.junit.platform.commons.util.AnnotationUtils; 12 | import org.junit.platform.commons.util.ReflectionUtils; 13 | 14 | import java.lang.reflect.Executable; 15 | import java.lang.reflect.Method; 16 | import java.lang.reflect.Parameter; 17 | import java.util.Optional; 18 | 19 | /** 20 | * Created by huairen on 2017/7/17. 21 | */ 22 | public class AutoTestParameterResolver implements ParameterResolver { 23 | 24 | private final Object[] arguments; 25 | 26 | AutoTestParameterResolver(Object[] arguments) { 27 | this.arguments = arguments; 28 | } 29 | 30 | @Override 31 | public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { 32 | Executable declaringExecutable = parameterContext.getParameter().getDeclaringExecutable(); 33 | Method testMethod = extensionContext.getTestMethod().orElse(null); 34 | return declaringExecutable.equals(testMethod) && parameterContext.getIndex() < arguments.length; 35 | } 36 | 37 | @Override 38 | public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) 39 | throws ParameterResolutionException { 40 | Object argument = arguments[parameterContext.getIndex()]; 41 | Parameter parameter = parameterContext.getParameter(); 42 | Optional annotation = AnnotationUtils.findAnnotation(parameter, ConvertWith.class); 43 | // @formatter:off 44 | ArgumentConverter argumentConverter = annotation.map(ConvertWith::value) 45 | .map(clazz -> (ArgumentConverter) ReflectionUtils.newInstance(clazz)) 46 | .map(converter -> AnnotationConsumerInitializer.initialize(parameter, converter)) 47 | .orElse(DefaultArgumentConverter.INSTANCE); 48 | // @formatter:on 49 | try { 50 | return argumentConverter.convert(argument, parameterContext); 51 | } catch (Exception ex) { 52 | throw new ParameterResolutionException("参数转换出错:" + parameter.getType().getName()+":"+parameter.getName(), 53 | ex); 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/DataDeal.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import com.csvreader.CsvWriter; 4 | import com.autotest.base.AutoTestBase; 5 | import com.autotest.utils.ProcessObject; 6 | import com.autotest.utils.StringUtils; 7 | import org.junit.jupiter.api.extension.ExtensionContext; 8 | import org.junit.jupiter.api.extension.ParameterResolutionException; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.core.LocalVariableTableParameterNameDiscoverer; 12 | 13 | import java.io.*; 14 | import java.lang.reflect.Field; 15 | import java.lang.reflect.Method; 16 | import java.lang.reflect.Modifier; 17 | import java.lang.reflect.Parameter; 18 | import java.net.URL; 19 | import java.util.*; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | 24 | /** 25 | * Created by huairen on 2017/7/14. 26 | */ 27 | public class DataDeal { 28 | 29 | private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create("AutoTestExtension", 30 | "DataDeal"); 31 | 32 | protected static final Logger logger = LoggerFactory.getLogger(DataDeal.class); 33 | 34 | 35 | public static List getParams(ExtensionContext context, String file) { 36 | if (null == file || file.isEmpty()) { 37 | throw new IllegalArgumentException("csv文件路径file的值不能为空"); 38 | } 39 | if (file.startsWith("/")) { 40 | file = file.substring(1); 41 | } 42 | Method m = context.getTestMethod().get(); 43 | List args = getVariables(context); 44 | URL url = Thread.currentThread().getContextClassLoader() 45 | .getResource("autotest/" + file); 46 | if (null == url) { 47 | String filep = context.getTestClass().get().getClassLoader().getResource(".").getFile(); 48 | String fileDir = filep.replace("target/test-classes/", "src/test/resources/autotest/") + file; 49 | createCsvFile(args, fileDir); 50 | throw new IllegalArgumentException("找不到csv文件,创建文件成功:" + fileDir); 51 | 52 | } 53 | String filePath = Thread.currentThread().getContextClassLoader() 54 | .getResource("autotest/" + file).getPath(); 55 | 56 | File fl = new File(filePath); 57 | BufferedReader reader = null; 58 | try { 59 | reader = new BufferedReader(new FileReader(fl)); 60 | List result = new ArrayList<>(); 61 | String[] pars; 62 | int lineNo = 0; 63 | String[] header = null; 64 | String line = null; 65 | List obs = new ArrayList<>(); 66 | while ((line = reader.readLine()) != null) { 67 | ++lineNo; 68 | if (lineNo == 1) { 69 | header = splitContent(line); 70 | } else { 71 | if (line.contains("~")) { 72 | line = line.replace("~", ""); 73 | } 74 | List list = new ArrayList<>(); 75 | HashMap map = parseLine(header, line, lineNo); 76 | obs.add(map); 77 | for (int n = 0; n < args.size(); n++) { 78 | String name = args.get(n).getName(); 79 | if (null != map.get(name)) { 80 | String val = map.get(name).toString().trim(); 81 | list.add(val); 82 | } else { 83 | String type = args.get(n).getType().getSimpleName(); 84 | if ("String".equals(type)) { 85 | list.add(""); 86 | continue; 87 | } else if ("int".equals(type) 88 | || "Integer".equals(type) 89 | || "long".equals(type) 90 | || "Long".equals(type) 91 | || "short".equals(type) 92 | || "Short".equals(type) 93 | || "byte".equals(type) 94 | || "Byte".equals(type) 95 | || "float".equals(type) 96 | || "Float".equals(type) 97 | || "double".equals(type) 98 | || "Double".equals(type) 99 | || "char".equals(type) 100 | || "Character".equals(type) 101 | ) { 102 | list.add("0"); 103 | continue; 104 | } else if ("boolean".equals(type)) { 105 | list.add("false"); 106 | continue; 107 | } else { 108 | list.add(""); 109 | } 110 | } 111 | } 112 | StringBuffer str = new StringBuffer(); 113 | Iterator iterator = list.iterator(); 114 | while (iterator.hasNext()) { 115 | str.append(iterator.next() + ","); 116 | } 117 | if (0 != str.length()) { 118 | result.add(str.deleteCharAt(str.length() - 1).toString()); 119 | } 120 | } 121 | } 122 | int times = result.size(); 123 | String methodName = context.getTestMethod().get().getName(); 124 | context.getStore(NAMESPACE).put("methodName", methodName); 125 | context.getStore(NAMESPACE).put("times", times); 126 | // return result.toArray(new String[result.size()]); 127 | return obs; 128 | } catch (FileNotFoundException e) { 129 | e.printStackTrace(); 130 | } catch (IOException e) { 131 | e.printStackTrace(); 132 | } 133 | return null; 134 | } 135 | 136 | private static Pattern pattern = Pattern.compile("\\{[^}]*\\}"); 137 | 138 | public static String[] splitContent(String input) { 139 | 140 | //过滤所有的json字符串 141 | Matcher match = pattern.matcher(input); 142 | while (match.find()) { 143 | if (!StringUtils.isBlank(match.group())) { 144 | throw new ParameterResolutionException("参数转换出错: " + match.group()); 145 | } 146 | } 147 | ArrayList result = new ArrayList(); 148 | char character = 0; 149 | StringBuilder value = new StringBuilder(); 150 | 151 | for (int i = 0; i < input.length(); ++i) { 152 | char previousCharacter = character; 153 | character = input.charAt(i); 154 | if (character != 44 && character != 124) { 155 | value.append(character); 156 | } else if (previousCharacter == 92) { 157 | value.setCharAt(value.length() - 1, character); 158 | } else { 159 | result.add(value.toString().trim()); 160 | value = new StringBuilder(); 161 | } 162 | } 163 | 164 | result.add(value.toString().trim()); 165 | return (String[]) result.toArray(new String[0]); 166 | } 167 | 168 | public static String replace(String text, String repl, String with) { 169 | return replace(text, repl, with, -1); 170 | } 171 | 172 | public static String replace(String text, String repl, String with, int max) { 173 | if ((text == null) || (repl == null) || (with == null) || (repl.length() == 0) 174 | || (max == 0)) { 175 | return text; 176 | } 177 | 178 | StringBuffer buf = new StringBuffer(text.length()); 179 | int start = 0; 180 | int end = 0; 181 | 182 | while ((end = text.indexOf(repl, start)) != -1) { 183 | buf.append(text.substring(start, end)).append(with); 184 | start = end + repl.length(); 185 | 186 | if (--max == 0) { 187 | break; 188 | } 189 | } 190 | 191 | buf.append(text.substring(start)); 192 | return buf.toString(); 193 | } 194 | 195 | private static HashMap parseLine(String[] header, String line, int lineNo) { 196 | HashMap parMap = new HashMap<>(); 197 | String[] params = splitContent(line); 198 | if (params.length != header.length) { 199 | throw new RuntimeException("数据文件:" + " 第" + lineNo + "行格式错误"); 200 | } else { 201 | for (int i = 0; i < header.length; ++i) { 202 | parMap.put(header[i], StringUtils.isBlank(params[i]) ? null : params[i]); 203 | } 204 | 205 | } 206 | return parMap; 207 | } 208 | 209 | 210 | /** 211 | * 获取方法的参数 212 | * 213 | * @param context 214 | * @return 215 | */ 216 | public static List getVariables(ExtensionContext context) { 217 | List list = new ArrayList(); 218 | Parameter[] parameters = context.getTestMethod().get().getParameters(); 219 | LocalVariableTableParameterNameDiscoverer u = 220 | new LocalVariableTableParameterNameDiscoverer(); 221 | String[] params = u.getParameterNames(context.getTestMethod().get()); 222 | for (int i = 0; i < parameters.length; i++) { 223 | Parame p = new Parame(); 224 | p.setName(params[i].trim()); 225 | p.setType(parameters[i].getType()); 226 | list.add(p); 227 | } 228 | 229 | return list; 230 | } 231 | 232 | public static void createCsvFile(List list, String filePath) { 233 | File excelfile = new File(filePath); 234 | if (!excelfile.exists()) { 235 | try { 236 | String dir = filePath.substring(0, filePath.lastIndexOf("/")); 237 | File dirFile = new File(dir); 238 | if (!dirFile.exists()) { 239 | dirFile.mkdir(); 240 | } 241 | List strs = new ArrayList<>(); 242 | CsvWriter cwriter = new CsvWriter(filePath); 243 | for (Iterator it = list.iterator(); it.hasNext(); ) { 244 | Parame p = (Parame) it.next(); 245 | Class clz = p.getType(); 246 | if (DataDeal.isJavaClass(clz) || clz.isEnum()) { 247 | if (!strs.contains(p.getName())) { 248 | strs.add(p.getName()); 249 | } 250 | } else { 251 | strs = getFieldFromClass(clz, strs, p.getName()); 252 | } 253 | } 254 | for (String s : strs) { 255 | cwriter.write(s, true); 256 | } 257 | cwriter.endRecord(); 258 | for (String s : strs) { 259 | String value = ""; 260 | if ("testId".equals(s)) { 261 | value = "1001"; 262 | } else { 263 | value = ""; 264 | } 265 | cwriter.write(value, true); 266 | } 267 | cwriter.flush();// 刷新数据 268 | } catch (IOException e) { 269 | e.printStackTrace(); 270 | } 271 | } else { 272 | logger.info("csv文件已存在!"); 273 | } 274 | } 275 | 276 | public static Object mapToObject(Map map, Class clz, String name) throws Exception { 277 | if (map == null) { 278 | return null; 279 | } 280 | Object obj = clz.newInstance(); 281 | List fields = new ArrayList<>(); 282 | fields = getClassAllFields(clz, fields); 283 | for (Field field : fields) { 284 | int mod = field.getModifiers(); 285 | if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { 286 | continue; 287 | } 288 | field.setAccessible(true); 289 | char ch = name.charAt(name.length() - 1); 290 | String str1 = field.getName() + ch + "_" + name.substring(0, name.length() - 1); 291 | String str2 = field.getName() + ch; 292 | String str3 = field.getName() + "_" + name; 293 | String str = null; 294 | if (Character.isDigit(ch)) { 295 | if (map.containsKey(str1)) { 296 | str = map.get(str1); 297 | } else if (map.containsKey(str2)) { 298 | str = map.get(str2); 299 | } 300 | field.set(obj, ProcessObject.processing(field.getType(), str)); 301 | continue; 302 | } else if (map.containsKey(str3)) { 303 | str = map.get(str3); 304 | field.set(obj, ProcessObject.processing(field.getType(), str)); 305 | continue; 306 | } 307 | field.set(obj, ProcessObject.processing(field.getType(), map.get(field.getName()))); 308 | } 309 | return obj; 310 | } 311 | 312 | public static List getFieldFromClass(Class clz, List strs, String name) { 313 | List fields = new ArrayList<>(); 314 | fields = getClassAllFields(clz, fields); 315 | for (Field field : fields) { 316 | if ("serialVersionUID".equals(field.getName())) { 317 | continue; 318 | } 319 | field.setAccessible(true); 320 | char ch = name.charAt(name.length() - 1); 321 | String str1 = field.getName() + ch + "_" + name.substring(0, name.length() - 1); 322 | String str2 = field.getName() + ch; 323 | String str3 = field.getName() + "_" + name; 324 | if (!strs.contains(field.getName())) { 325 | strs.add(field.getName()); 326 | } else if (Character.isDigit(ch)) { 327 | if (!strs.contains(str2)) { 328 | strs.add(str2); 329 | } else if (!strs.contains(str1)) { 330 | strs.add(str1); 331 | } 332 | } else if (!strs.contains(str3)) { 333 | strs.add(str3); 334 | } 335 | } 336 | return strs; 337 | } 338 | 339 | /** 340 | * 循环向上转型, 获取对象的 DeclaredField 341 | * 342 | * @param 343 | * @param 344 | * @return 345 | */ 346 | 347 | public static List getClassAllFields(Class clazz, List allGenericFields) { 348 | 349 | // 如果clazz为空则直接返回 350 | if (clazz == null) { 351 | return allGenericFields; 352 | } 353 | Object parent = clazz.getGenericSuperclass(); 354 | // 如果有父类并且父类不是Object 则递归调用 355 | if (parent != null && !((Class) parent).getName().equals("Object")) { 356 | getClassAllFields((Class) parent, allGenericFields); 357 | } 358 | Field[] fields = clazz.getDeclaredFields(); 359 | if (fields != null) {// 如果clazz存在声明的属性 360 | for (int i = 0; i < fields.length; i++) 361 | allGenericFields.add(fields[i]); 362 | } 363 | 364 | return allGenericFields; 365 | } 366 | 367 | public static boolean isJavaClass(Class clz) { 368 | return clz != null && clz.getClassLoader() == null; 369 | } 370 | 371 | public static String toLowerCaseFirstOne(String s) { 372 | if (Character.isLowerCase(s.charAt(0))) { 373 | return s; 374 | } else { 375 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 376 | } 377 | } 378 | 379 | } 380 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/extension/Parame.java: -------------------------------------------------------------------------------- 1 | package com.autotest.extension; 2 | 3 | import java.lang.annotation.Annotation; 4 | 5 | /** 6 | * Created by huairen on 2017/7/20. 7 | */ 8 | public class Parame 9 | { 10 | 11 | /** 12 | * 参数名 13 | */ 14 | private String name; 15 | 16 | /** 17 | * 参数类型 18 | */ 19 | private Class type; 20 | 21 | /** 22 | * 参数对应annotation 23 | */ 24 | private Annotation annotation; 25 | 26 | /** 27 | * 对象值 28 | */ 29 | private String value; 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | public Class getType() { 40 | return type; 41 | } 42 | 43 | public void setType(Class type) { 44 | this.type = type; 45 | } 46 | 47 | public Annotation getAnnotation() { 48 | return annotation; 49 | } 50 | 51 | public void setAnnotation(Annotation annotation) { 52 | this.annotation = annotation; 53 | } 54 | 55 | public String getValue() { 56 | return value; 57 | } 58 | 59 | public void setValue(String value) { 60 | this.value = value; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "Parameter{" + 66 | "name='" + name + '\'' + 67 | ", type=" + type + 68 | ", annotation=" + annotation + 69 | ", value='" + value + '\'' + 70 | '}'; 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/generate/ApiParameter.java: -------------------------------------------------------------------------------- 1 | package com.autotest.generate; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | 5 | /** 6 | * Created by huairen on 2017/8/16. 7 | */ 8 | public class ApiParameter { 9 | /** 10 | * 字段名 11 | */ 12 | private String itemCode; 13 | /** 14 | * 二级字段名 15 | */ 16 | private String secondCode; 17 | 18 | /** 19 | * 字段中文名 20 | */ 21 | private String itemTitle; 22 | 23 | /** 24 | * 参数请求类型 25 | */ 26 | private String paramType; 27 | 28 | /** 29 | * 参数所属service 30 | */ 31 | private String serviceId; 32 | 33 | /** 34 | * 必填 35 | */ 36 | private String fullStatus; 37 | 38 | /** 39 | * 参数长度 40 | */ 41 | private String sizeScope; 42 | 43 | /** 44 | * 子参数 45 | */ 46 | private JSONArray children; 47 | 48 | /** 49 | * 父参数 50 | */ 51 | private String father; 52 | 53 | /** 54 | * 层级 55 | */ 56 | private int layer; 57 | 58 | /** 59 | * 字段类型 60 | */ 61 | private String valType; 62 | 63 | /** 64 | * 版本号 65 | */ 66 | private String version; 67 | 68 | /** 69 | * 可用 70 | */ 71 | private boolean visible; 72 | 73 | /** 74 | * 示例 75 | */ 76 | 77 | private String demo; 78 | 79 | /** 80 | * 说明 81 | */ 82 | private String descn; 83 | 84 | /** 85 | * 新参数 86 | */ 87 | private boolean newest ; 88 | 89 | public String getItemCode() { 90 | return itemCode; 91 | } 92 | public void setItemCode(String itemCode) { 93 | this.itemCode = itemCode; 94 | } 95 | 96 | public String getSecondCode() { 97 | return secondCode; 98 | } 99 | public void setSecondCode(String secondCode) { 100 | this.secondCode = secondCode; 101 | } 102 | public String getItemTitle() { 103 | return itemTitle; 104 | } 105 | public void setItemTitle(String itemTitle) { 106 | this.itemTitle = itemTitle; 107 | } 108 | public String getParamType() { 109 | return paramType; 110 | } 111 | public void setParamType(String paramType) { 112 | this.paramType = paramType; 113 | } 114 | public String getServiceId() { 115 | return serviceId; 116 | } 117 | public void setServiceId(String serviceId) { 118 | this.serviceId = serviceId; 119 | } 120 | public String getFullStatus() { 121 | return fullStatus; 122 | } 123 | public void setFullStatus(String fullStatus) { 124 | this.fullStatus = fullStatus; 125 | } 126 | public String getSizeScope() { 127 | return sizeScope; 128 | } 129 | public void setSizeScope(String sizeScope) { 130 | this.sizeScope = sizeScope; 131 | } 132 | public JSONArray getChildren() { 133 | return children; 134 | } 135 | public void setChildren(JSONArray children) { 136 | this.children = children; 137 | } 138 | 139 | public String getFather() { 140 | return father; 141 | } 142 | public void setFather(String father) { 143 | this.father = father; 144 | } 145 | 146 | public int getLayer() { 147 | return layer; 148 | } 149 | public void setLayer(int layer) { 150 | this.layer = layer; 151 | } 152 | public String getValType() { 153 | return valType; 154 | } 155 | public void setValType(String valType) { 156 | this.valType = valType; 157 | } 158 | public String getVersion() { 159 | return version; 160 | } 161 | public void setVersion(String version) { 162 | this.version = version; 163 | } 164 | 165 | public boolean isVisible() { 166 | return visible; 167 | } 168 | public void setVisible(boolean visible) { 169 | this.visible = visible; 170 | } 171 | 172 | public String getDemo() { 173 | return demo; 174 | } 175 | public void setDemo(String demo) { 176 | this.demo = demo; 177 | } 178 | public String getDescn() { 179 | return descn; 180 | } 181 | public void setDescn(String descn) { 182 | this.descn = descn; 183 | } 184 | public boolean isNewest() { 185 | return newest; 186 | } 187 | public void setNewest(boolean newest) { 188 | this.newest = newest; 189 | } 190 | @Override 191 | public String toString() { 192 | return "ApiParameter [itemCode=" + itemCode + ", secondCode=" + secondCode + ", itemTitle=" + itemTitle 193 | + ", paramType=" + paramType + ", serviceId=" + serviceId + ", fullStatus=" + fullStatus 194 | + ", sizeScope=" + sizeScope + ", children=" + children + ", father=" + father + ", layer=" + layer 195 | + ", valType=" + valType + ", version=" + version + ", visible=" + visible + ", demo=" + demo 196 | + ", descn=" + descn + ", newest=" + newest + "]"; 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/generate/GenerateBase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.generate; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.Template; 5 | import freemarker.template.TemplateExceptionHandler; 6 | import org.mybatis.generator.api.GeneratedJavaFile; 7 | import org.mybatis.generator.api.dom.java.Field; 8 | import org.mybatis.generator.api.dom.java.TopLevelClass; 9 | 10 | import java.io.BufferedWriter; 11 | import java.io.File; 12 | import java.io.FileWriter; 13 | import java.io.PrintWriter; 14 | import java.math.BigDecimal; 15 | import java.math.BigInteger; 16 | import java.net.URL; 17 | import java.text.SimpleDateFormat; 18 | import java.util.*; 19 | 20 | /** 21 | * Created by yu on 17/12/22. 22 | */ 23 | public class GenerateBase { 24 | 25 | /** 26 | * 根据项目名称生成base类 27 | * 28 | * @param projectName 29 | * @return 30 | */ 31 | public void generateBase(String projectName, List generatedJavaFiles, boolean covered) { 32 | try { 33 | List> tableList = new ArrayList<>(); 34 | List fileNames = new ArrayList<>(); 35 | for (GeneratedJavaFile gjf : generatedJavaFiles) { 36 | if (gjf.getCompilationUnit().getType().getShortNameWithoutTypeArguments().endsWith("DO")) { 37 | fileNames.add(gjf.getCompilationUnit().getType().getShortNameWithoutTypeArguments()); 38 | } 39 | } 40 | Collections.sort(fileNames); 41 | for (String fileName : fileNames) { 42 | for (GeneratedJavaFile gjf : generatedJavaFiles) { 43 | if (fileName.equals(gjf.getCompilationUnit().getType().getShortNameWithoutTypeArguments())) { 44 | Map tableMap = new HashMap(); 45 | tableMap.put("tableName", gjf.getCompilationUnit().getType().getShortNameWithoutTypeArguments() 46 | .replace("DO", "")); 47 | List pars = new ArrayList<>(); 48 | TopLevelClass tlc = (TopLevelClass) gjf.getCompilationUnit(); 49 | List list = tlc.getAnnotations(); 50 | String table= null; 51 | for (String s : list) { 52 | if (s.contains("@Table(name =")) { 53 | table = s.split("\"")[1]; 54 | } 55 | } 56 | tableMap.put("table",table); 57 | for (Field f : tlc.getFields()) { 58 | if ("serialVersionUID".equals(f.getName())) { 59 | continue; 60 | } 61 | Param par = new Param(); 62 | par.setName(f.getName()); 63 | par.setTypeName(f.getType().getShortNameWithoutTypeArguments()); 64 | if ("Long".equals(par.getTypeName())) { 65 | par.setTypeName("long"); 66 | } 67 | List strs = f.getAnnotations(); 68 | String clumnName = ""; 69 | for (String str : strs) { 70 | if (str.contains("@Column(name =")) { 71 | clumnName = str.split("\"")[1]; 72 | if (clumnName.split("_").length > 1 && clumnName.split("_")[0].length() == 1) { 73 | par.setAnnotation(clumnName); 74 | } 75 | } 76 | } 77 | pars.add(par); 78 | } 79 | tableMap.put("pars", pars); 80 | tableList.add(tableMap); 81 | } 82 | } 83 | } 84 | // AutoTestBase类 85 | String className = toUpperCaseFirstOne(projectName) + "TestBase"; 86 | String filePath = Thread.currentThread().getContextClassLoader().getResource("ftl/").getPath() 87 | .replace("/target/test-classes", "/src/test/resources"); 88 | String outFile = getClassFilePath(GenerateBase.class).replace("\\target\\classes", "\\src\\test\\java") 89 | .replace("generate\\" + GenerateBase.class.getSimpleName() + ".class", "testbase\\" 90 | + className + ".java"); 91 | String packageName = "com.autotest.testbase"; 92 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_26); 93 | cfg.setDirectoryForTemplateLoading(new File(filePath)); 94 | cfg.setDefaultEncoding("UTF-8"); 95 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 96 | 97 | Map root = new HashMap(); 98 | root.put("packageName", packageName); 99 | root.put("projectName", projectName); 100 | root.put("className", className); 101 | root.put("time", new SimpleDateFormat("yyyy/MM/dd").format(new Date())); 102 | root.put("author", "autotest"); 103 | root.put("tableList", tableList); 104 | if (covered || !new File(outFile).exists()) { 105 | Template template = cfg.getTemplate("generateTestBase.ftl"); 106 | PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); 107 | template.process(root, out); 108 | System.out.println("更新成功" + outFile); 109 | } 110 | 111 | // DataSourceConfig类 112 | String className3 = toUpperCaseFirstOne(projectName) + "DataSourceConfig"; 113 | String outFile3 = getClassFilePath(GenerateBase.class).replace("\\target\\classes", "\\src\\main\\java") 114 | .replace("generate\\" + GenerateBase.class.getSimpleName() + ".class", "config\\" 115 | + className3 + ".java"); 116 | if (covered || !new File(outFile3).exists()) { 117 | Template template3 = cfg.getTemplate("generateDataSourceConfig.ftl"); 118 | PrintWriter out3 = new PrintWriter(new BufferedWriter(new FileWriter(outFile3))); 119 | root.put("className", className3); 120 | template3.process(root, out3); 121 | System.out.println("更新成功" + outFile3); 122 | } 123 | 124 | } catch (Exception e) { 125 | e.printStackTrace(); 126 | } 127 | 128 | } 129 | 130 | /** 131 | * 得到当前类的路径 132 | * 133 | * @param clazz 134 | * @return 135 | */ 136 | public static String getClassFilePath(Class clazz) { 137 | try { 138 | return java.net.URLDecoder.decode(getClassFile(clazz).getAbsolutePath(), "UTF-8"); 139 | } catch (Exception e) { 140 | e.printStackTrace(); 141 | return ""; 142 | } 143 | } 144 | 145 | /** 146 | * 取得当前类所在的文件 147 | * 148 | * @param clazz 149 | * @return 150 | */ 151 | public static File getClassFile(Class clazz) { 152 | URL path = clazz.getResource(clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1) + ".classs"); 153 | if (path == null) { 154 | String name = clazz.getName().replaceAll("[.]", "/"); 155 | path = clazz.getResource("/" + name + ".class"); 156 | } 157 | return new File(path.getFile()); 158 | } 159 | 160 | /** 161 | * 首字母转小写 162 | * 163 | * @param s 164 | * @return 165 | */ 166 | public static String toLowerCaseFirstOne(String s) { 167 | if (Character.isLowerCase(s.charAt(0))) { 168 | return s; 169 | } else { 170 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 171 | } 172 | } 173 | 174 | /** 175 | * 首字母转大写 176 | * 177 | * @param s 178 | * @return 179 | */ 180 | public static String toUpperCaseFirstOne(String s) { 181 | if (Character.isUpperCase(s.charAt(0))) { 182 | return s; 183 | } else { 184 | return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString(); 185 | } 186 | } 187 | 188 | 189 | /** 190 | * 判断一个类是否为基本数据类型。 191 | * 192 | * @param clazz 要判断的类。 193 | * @return true 表示为基本数据类型。 194 | */ 195 | protected boolean isBaseDataType(Class clazz) throws Exception { 196 | return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) 197 | || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) 198 | || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) 199 | || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || 200 | // clazz.equals(Date.class) || 201 | // clazz.equals(Money.class) || 202 | clazz.isEnum() || clazz.isPrimitive()); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/generate/GenerateBaseFile.java: -------------------------------------------------------------------------------- 1 | package com.autotest.generate; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.Template; 5 | import freemarker.template.TemplateExceptionHandler; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.persistence.Column; 10 | import java.io.*; 11 | import java.lang.reflect.Field; 12 | import java.math.BigDecimal; 13 | import java.math.BigInteger; 14 | import java.net.JarURLConnection; 15 | import java.net.URL; 16 | import java.net.URLDecoder; 17 | import java.text.SimpleDateFormat; 18 | import java.util.*; 19 | import java.util.jar.JarEntry; 20 | import java.util.jar.JarFile; 21 | 22 | /** 23 | * Created by huairen on 2017/8/17. 24 | */ 25 | public class GenerateBaseFile { 26 | 27 | protected final static Logger log = LoggerFactory.getLogger(GenerateBaseFile.class); 28 | 29 | public static void main(String[] args) { 30 | String projectName = "platfrompay"; 31 | 32 | new GenerateBaseFile().generateBaseFile(projectName, "huairen", false, GenerateBaseFile.class); 33 | 34 | } 35 | 36 | 37 | /** 38 | * 根据项目名称生成base类 39 | * 40 | * @param projectName 41 | * @return 42 | */ 43 | public void generateBaseFile(String projectName, String author, boolean covered, Class cla) { 44 | try { 45 | // Class cla = Class.forName(clazzName); 46 | // 从包路径获取全部DOclass类 47 | Set> cls = getClasses("dal.model." + projectName); 48 | List> tableList = new ArrayList<>(); 49 | for (Class c : cls) { 50 | if (!c.getName().contains("Example")) { 51 | System.out.println(c.getName()); 52 | Map table = new HashMap(); 53 | table.put("tableName", c.getSimpleName().replace("DO", "")); 54 | List pars = new ArrayList<>(); 55 | Field[] fields = c.getDeclaredFields(); 56 | for (Field f : fields) { 57 | if ("serialVersionUID".equals(f.getName())) { 58 | continue; 59 | } 60 | Param par = new Param(); 61 | par.setName(f.getName()); 62 | par.setTypeName(f.getType().getSimpleName()); 63 | if ("Long".equals(f.getType().getSimpleName())) { 64 | par.setTypeName("long"); 65 | } 66 | Column column = f.getAnnotation(Column.class); 67 | if (null != column) { 68 | String clumnName = column.name(); 69 | if (clumnName.split("_").length > 1 && clumnName.split("_")[0].length() == 1) { 70 | par.setAnnotation(column.name()); 71 | } 72 | } 73 | pars.add(par); 74 | } 75 | table.put("pars", pars); 76 | tableList.add(table); 77 | } 78 | } 79 | // AutoTestBase类 80 | String className = toUpperCaseFirstOne(projectName) + "TestBase"; 81 | String filePath = Thread.currentThread().getContextClassLoader().getResource("ftl/").getPath() 82 | .replace("/target/test-classes", "/src/test/resources"); 83 | String outFile = getClassFilePath(cla).replace("\\target\\classes", "\\src\\test\\java") 84 | .replace(cla.getSimpleName() + ".class", className + ".java"); 85 | String packageName = cla.getPackage().getName(); 86 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_26); 87 | cfg.setDirectoryForTemplateLoading(new File(filePath)); 88 | cfg.setDefaultEncoding("UTF-8"); 89 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 90 | 91 | Map root = new HashMap(); 92 | root.put("packageName", packageName); 93 | root.put("projectName", projectName); 94 | root.put("className", className); 95 | root.put("time", new SimpleDateFormat("yyyy/MM/dd").format(new Date())); 96 | root.put("author", author); 97 | root.put("tableList", tableList); 98 | if (covered || !new File(outFile).exists()) { 99 | Template template = cfg.getTemplate("generateTestBase.ftl"); 100 | PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); 101 | template.process(root, out); 102 | System.out.println("更新成功" + outFile); 103 | } 104 | 105 | // DataSourceConfig类 106 | String className3 = toUpperCaseFirstOne(projectName) + "DataSourceConfig"; 107 | String outFile3 = getClassFilePath(cla).replace("\\target\\classes", "\\src\\test\\java") 108 | .replace("testbase\\" + cla.getSimpleName() + ".class", "datasource\\" 109 | + className3 + ".java"); 110 | if (covered || !new File(outFile3).exists()) { 111 | Template template3 = cfg.getTemplate("generateDataSourceConfig.ftl"); 112 | PrintWriter out3 = new PrintWriter(new BufferedWriter(new FileWriter(outFile3))); 113 | root.put("className", className3); 114 | template3.process(root, out3); 115 | System.out.println("更新成功" + outFile3); 116 | } 117 | 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | } 121 | 122 | } 123 | 124 | /** 125 | * 得到当前类的路径 126 | * 127 | * @param clazz 128 | * @return 129 | */ 130 | public static String getClassFilePath(Class clazz) { 131 | try { 132 | return java.net.URLDecoder.decode(getClassFile(clazz).getAbsolutePath(), "UTF-8"); 133 | } catch (Exception e) { 134 | e.printStackTrace(); 135 | return ""; 136 | } 137 | } 138 | 139 | /** 140 | * 取得当前类所在的文件 141 | * 142 | * @param clazz 143 | * @return 144 | */ 145 | public static File getClassFile(Class clazz) { 146 | URL path = clazz.getResource(clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1) + ".classs"); 147 | if (path == null) { 148 | String name = clazz.getName().replaceAll("[.]", "/"); 149 | path = clazz.getResource("/" + name + ".class"); 150 | } 151 | return new File(path.getFile()); 152 | } 153 | 154 | /** 155 | * 首字母转小写 156 | * 157 | * @param s 158 | * @return 159 | */ 160 | public static String toLowerCaseFirstOne(String s) { 161 | if (Character.isLowerCase(s.charAt(0))) { 162 | return s; 163 | } else { 164 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 165 | } 166 | } 167 | 168 | /** 169 | * 首字母转大写 170 | * 171 | * @param s 172 | * @return 173 | */ 174 | public static String toUpperCaseFirstOne(String s) { 175 | if (Character.isUpperCase(s.charAt(0))) { 176 | return s; 177 | } else { 178 | return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString(); 179 | } 180 | } 181 | 182 | /** 183 | * 从包package中获取所有的Class 184 | * 185 | * @param pack 186 | * @return 187 | */ 188 | public static Set> getClasses(String pack) { 189 | 190 | // 第一个class类的集合 191 | Set> classes = new LinkedHashSet>(); 192 | // 是否循环迭代 193 | boolean recursive = true; 194 | // 获取包的名字 并进行替换 195 | String packageName = pack; 196 | String packageDirName = packageName.replace('.', '/'); 197 | // 定义一个枚举的集合 并进行循环来处理这个目录下的things 198 | Enumeration dirs; 199 | try { 200 | dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); 201 | // 循环迭代下去 202 | while (dirs.hasMoreElements()) { 203 | // 获取下一个元素 204 | URL url = dirs.nextElement(); 205 | // 得到协议的名称 206 | String protocol = url.getProtocol(); 207 | // 如果是以文件的形式保存在服务器上 208 | if ("file".equals(protocol)) { 209 | // System.err.println("file类型的扫描"); 210 | // 获取包的物理路径 211 | String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); 212 | // 以文件的方式扫描整个包下的文件 并添加到集合中 213 | findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); 214 | } else if ("jar".equals(protocol)) { 215 | // 如果是jar包文件 216 | // 定义一个JarFile 217 | // System.err.println("jar类型的扫描"); 218 | JarFile jar; 219 | try { 220 | // 获取jar 221 | jar = ((JarURLConnection) url.openConnection()).getJarFile(); 222 | // 从此jar包 得到一个枚举类 223 | Enumeration entries = jar.entries(); 224 | // 同样的进行循环迭代 225 | while (entries.hasMoreElements()) { 226 | // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 227 | JarEntry entry = entries.nextElement(); 228 | String name = entry.getName(); 229 | // 如果是以/开头的 230 | if (name.charAt(0) == '/') { 231 | // 获取后面的字符串 232 | name = name.substring(1); 233 | } 234 | // 如果前半部分和定义的包名相同 235 | if (name.startsWith(packageDirName)) { 236 | int idx = name.lastIndexOf('/'); 237 | // 如果以"/"结尾 是一个包 238 | if (idx != -1) { 239 | // 获取包名 把"/"替换成"." 240 | packageName = name.substring(0, idx).replace('/', '.'); 241 | } 242 | // 如果可以迭代下去 并且是一个包 243 | if ((idx != -1) || recursive) { 244 | // 如果是一个.class文件 而且不是目录 245 | if (name.endsWith(".class") && !entry.isDirectory()) { 246 | // 去掉后面的".class" 获取真正的类名 247 | String className = name.substring(packageName.length() + 1, name.length() - 6); 248 | try { 249 | // 添加到classes 250 | classes.add(Class.forName(packageName + '.' + className)); 251 | } catch (ClassNotFoundException e) { 252 | // log 253 | // .error("添加用户自定义视图类错误 254 | // 找不到此类的.class文件"); 255 | e.printStackTrace(); 256 | } 257 | } 258 | } 259 | } 260 | } 261 | } catch (IOException e) { 262 | // log.error("在扫描用户定义视图时从jar包获取文件出错"); 263 | e.printStackTrace(); 264 | } 265 | } 266 | } 267 | } catch (IOException e) { 268 | e.printStackTrace(); 269 | } 270 | 271 | return classes; 272 | } 273 | 274 | /** 275 | * 以文件的形式来获取包下的所有Class 276 | * 277 | * @param packageName 278 | * @param packagePath 279 | * @param recursive 280 | * @param classes 281 | */ 282 | public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean 283 | recursive, 284 | Set> classes) { 285 | // 获取此包的目录 建立一个File 286 | File dir = new File(packagePath); 287 | // 如果不存在或者 也不是目录就直接返回 288 | if (!dir.exists() || !dir.isDirectory()) { 289 | // log.warn("用户定义包名 " + packageName + " 下没有任何文件"); 290 | return; 291 | } 292 | // 如果存在 就获取包下的所有文件 包括目录 293 | File[] dirfiles = dir.listFiles(new FileFilter() { 294 | // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) 295 | @Override 296 | public boolean accept(File file) { 297 | return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); 298 | } 299 | }); 300 | // 循环所有文件 301 | for (File file : dirfiles) { 302 | // 如果是目录 则继续扫描 303 | if (file.isDirectory()) { 304 | findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, 305 | classes); 306 | } else { 307 | // 如果是java类文件 去掉后面的.class 只留下类名 308 | String className = file.getName().substring(0, file.getName().length() - 6); 309 | try { 310 | // 添加到集合中去 311 | // classes.add(Class.forName(packageName + '.' + 312 | // className)); 313 | classes.add( 314 | Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className)); 315 | } catch (ClassNotFoundException e) { 316 | e.printStackTrace(); 317 | } 318 | } 319 | } 320 | } 321 | 322 | 323 | /** 324 | * 循环向上转型, 获取对象的 DeclaredField 325 | * 326 | * @param 327 | * @param 328 | * @return 329 | */ 330 | 331 | public List getClassAllFields(Class clazz, List allGenericFields) { 332 | 333 | // 如果clazz为空则直接返回 334 | if (clazz == null) { 335 | return allGenericFields; 336 | } 337 | Object parent = clazz.getGenericSuperclass(); 338 | // 如果有父类并且父类不是Object 则递归调用 339 | if (parent != null && !((Class) parent).getName().equals("Object")) { 340 | getClassAllFields((Class) parent, allGenericFields); 341 | } 342 | Field[] fields = clazz.getDeclaredFields(); 343 | if (fields != null) {// 如果clazz存在声明的属性 344 | for (int i = 0; i < fields.length; i++) 345 | allGenericFields.add(fields[i]); 346 | } 347 | 348 | return allGenericFields; 349 | } 350 | 351 | /** 352 | * 判断一个类是否为基本数据类型。 353 | * 354 | * @param clazz 要判断的类。 355 | * @return true 表示为基本数据类型。 356 | */ 357 | protected boolean isBaseDataType(Class clazz) throws Exception { 358 | return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) 359 | || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) 360 | || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) 361 | || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || 362 | // clazz.equals(Date.class) || 363 | // clazz.equals(Money.class) || 364 | clazz.isEnum() || clazz.isPrimitive()); 365 | } 366 | 367 | 368 | } -------------------------------------------------------------------------------- /src/main/java/com/autotest/generate/GenerateFacadeCase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.generate; 2 | 3 | 4 | import freemarker.template.Configuration; 5 | import freemarker.template.Template; 6 | import freemarker.template.TemplateExceptionHandler; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.io.BufferedWriter; 11 | import java.io.File; 12 | import java.io.FileWriter; 13 | import java.io.PrintWriter; 14 | import java.lang.annotation.Annotation; 15 | import java.lang.reflect.*; 16 | import java.text.SimpleDateFormat; 17 | import java.util.*; 18 | 19 | /** 20 | * Created by huairen on 2018/5/22. 21 | */ 22 | public class GenerateFacadeCase extends GenerateBaseFile { 23 | protected final Logger log = LoggerFactory.getLogger(this.getClass().getName()); 24 | 25 | 26 | /** 27 | * 生成测试代码 28 | */ 29 | public void generate(Class facadeCla, String methodName, String packag, String author, Class claz) { 30 | String resultType = ""; 31 | String resultName = ""; 32 | String orderType = ""; 33 | String orderName = ""; 34 | String facadeType = facadeCla.getTypeName(); 35 | 36 | String facadeName = facadeCla.getSimpleName(); 37 | Method[] methods = facadeCla.getDeclaredMethods(); 38 | int time = 0; 39 | for (Method m : methods) { 40 | if (!"all".equals(methodName)) { 41 | if (null != methodName && !methodName.equals(m.getName())) { 42 | continue; 43 | } 44 | } 45 | time++; 46 | resultType = m.getReturnType().getName(); 47 | System.out.println(resultType); 48 | resultName = m.getReturnType().getSimpleName(); 49 | System.out.println(resultName); 50 | // 参数 51 | List pars = new ArrayList<>(); 52 | // order 53 | List pars_order = new ArrayList<>(); 54 | Parameter[] parameters = m.getParameters(); 55 | for (Parameter p : parameters) { 56 | orderType = p.getType().getName(); 57 | orderName = p.getName(); 58 | if (orderType.contains("UniformStringQueryOrder")) { 59 | break; 60 | } 61 | Param parameter = new Param(); 62 | parameter.setName(orderName); 63 | parameter.setSecondName(orderName); 64 | parameter.setType(orderType); 65 | parameter.setTypeName(orderType.split("\\.")[orderType.split("\\.").length - 1]); 66 | parameter.setLayer(0); 67 | Class cla = p.getType(); 68 | try { 69 | if (isBaseDataType(cla)) { 70 | parameter.setPrimitive("yes"); 71 | pars.add(parameter); 72 | continue; 73 | } 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | } 77 | pars_order.add(parameter); 78 | 79 | List allGenericFields = new ArrayList(); 80 | allGenericFields = getClassAllFields(cla, allGenericFields); 81 | for (Field f : allGenericFields) { 82 | System.out.println(f.getName()); 83 | if ("serialVersionUID".equals(f.getName())) { 84 | continue; 85 | } 86 | // 设置允许访问 87 | f.setAccessible(true); 88 | Param par = new Param(); 89 | par.setName(f.getName()); 90 | par.setType(f.getType().getName()); 91 | par.setTypeName(f.getType().getName().split("\\.")[f.getType().getName().split("\\.").length - 1]); 92 | par.setFather(orderName); 93 | par.setOrder(orderName); 94 | par.setLayer(1); 95 | try { 96 | if (isBaseDataType(f.getType())) { 97 | par.setPrimitive("yes"); 98 | } 99 | } catch (Exception e) { 100 | e.printStackTrace(); 101 | } 102 | for (Annotation ann : f.getDeclaredAnnotations()) { 103 | if ("NotBlank".equals(ann.annotationType().getSimpleName()) 104 | || "NotEmpty".equals(ann.annotationType().getSimpleName()) 105 | || "NotNull".equals(ann.annotationType().getSimpleName())) { 106 | par.setAnnotation("NotNull"); 107 | } 108 | } 109 | if ("List".equals(f.getType().getSimpleName())) { 110 | Type t = f.getGenericType(); 111 | if (t instanceof ParameterizedType) { 112 | ParameterizedType pt = (ParameterizedType) t; 113 | Class clz = (Class) pt.getActualTypeArguments()[0]; 114 | par.setChildren(toLowerCaseFirstOne( 115 | clz.getName().split("\\.")[clz.getName().split("\\.").length - 1])); 116 | par.setChildrenCLass(clz.getName()); 117 | // 向pars里加参数 118 | addParameter(clz, par, pars); 119 | } 120 | } 121 | try { 122 | if (!isBaseDataType(f.getType()) && f.getType().getSimpleName().contains("Order")) { 123 | // 向pars里加参数 124 | addParameter(f.getType(), par, pars); 125 | } 126 | } catch (Exception e) { 127 | e.printStackTrace(); 128 | } 129 | pars.add(par); 130 | } 131 | } 132 | // 第三层参数 133 | ArrayList ls = new ArrayList<>(); 134 | for (int j = 0; j < pars.size(); j++) { 135 | Param p = pars.get(j); 136 | if (2 == p.getLayer() && "List".equals(p.getTypeName()) && !ls.contains(p.getChildren())) { 137 | Class cl = null; 138 | try { 139 | cl = Class.forName(p.getChildrenCLass()); 140 | } catch (ClassNotFoundException e2) { 141 | e2.printStackTrace(); 142 | } 143 | addParameter(cl, p, pars); 144 | ls.add(p.getChildren()); 145 | } 146 | } 147 | for (Param p : pars) { 148 | if (null == p.getSecondName()) { 149 | p.setSecondName(p.getName()); 150 | } 151 | System.out.println(p); 152 | } 153 | // 形参 154 | ArrayList childlist = new ArrayList<>(); 155 | for (Param p : pars) { 156 | try { 157 | if (p.getFather() == null 158 | && !childlist.contains(p.getName()) 159 | && !isBaseDataType(Class.forName(p.getType()))) { 160 | childlist.add(p.getName()); 161 | } 162 | } catch (Exception e2) { 163 | e2.printStackTrace(); 164 | } 165 | } 166 | for (int j = 0; j < childlist.size(); j++) { 167 | for (Param p : pars) { 168 | if (null == p.getOrder() || "List".equals(p.getTypeName()) || "Date".equals(p.getTypeName())) { 169 | childlist.remove(p.getSecondName()); 170 | } 171 | } 172 | } 173 | System.out.println(childlist); 174 | // pars_order 175 | Set orderlist = new HashSet<>(); 176 | for (int i = 0; i < pars.size(); i++) { 177 | Param para = pars.get(i); 178 | if (null != para.getChildrenCLass()) { 179 | Param par = new Param(); 180 | par.setName(toLowerCaseFirstOne( 181 | para.getChildrenCLass().split("\\.")[para.getChildrenCLass().split("\\.").length - 1])); 182 | par.setSecondName(para.getSecondName() + "_" + par.getName()); 183 | par.setTypeName( 184 | para.getChildrenCLass().split("\\.")[para.getChildrenCLass().split("\\.").length - 1]); 185 | par.setType(para.getChildrenCLass()); 186 | par.setFather(para.getSecondName()); 187 | par.setLayer(para.getLayer()); 188 | if (null == par.getName() || null == par.getTypeName()) { 189 | continue; 190 | } 191 | if (2 == par.getLayer() && orderlist.contains(par.getName())) { 192 | continue; 193 | } 194 | orderlist.add(par.getName()); 195 | pars_order.add(par); 196 | } 197 | if (null == para.getPrimitive() && para.getTypeName().contains("Order")) { 198 | orderlist.add(para.getName()); 199 | pars_order.add(para); 200 | } 201 | } 202 | System.out.println(orderlist); 203 | System.out.println(pars_order); 204 | Set importlist = new HashSet<>(); 205 | for (Param p : pars_order) { 206 | importlist.add(p.getType()); 207 | } 208 | 209 | // 类名 210 | String className = toUpperCaseFirstOne(facadeName) + toUpperCaseFirstOne(m.getName()) + "Test"; 211 | String filePath = Thread.currentThread().getContextClassLoader() 212 | .getResource("ftl/").getPath().replace("/target/test-classes", 213 | "/src/test/resources"); 214 | String outFile = getClassFilePath(claz) 215 | .replace("\\target\\classes", "\\src\\test\\java") 216 | .replace("\\target\\test-classes", "\\src\\test\\java") 217 | .replace(claz.getName().split("\\.")[claz.getName().split("\\.").length - 1] + ".class", 218 | packag.replace(".", "\\") + "\\"); 219 | String packageName = "com.autotest." + packag.replace("/", "."); 220 | String projectName = packag.indexOf(".") == -1 ? packag : packag.substring(0, packag.indexOf(".")); 221 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_26); 222 | try { 223 | cfg.setDirectoryForTemplateLoading(new File(filePath)); 224 | 225 | cfg.setDefaultEncoding("UTF-8"); 226 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 227 | 228 | Map root = new HashMap(); 229 | root.put("packageName", packageName); 230 | root.put("projectName", projectName); 231 | root.put("className", className); 232 | root.put("funcName", toLowerCaseFirstOne(className)); 233 | root.put("author", author); 234 | root.put("resultType", resultType); 235 | root.put("resultName", resultName); 236 | root.put("orderType", orderType); 237 | root.put("orderName", orderName); 238 | root.put("facadeName", facadeName); 239 | root.put("facadeType", facadeType); 240 | root.put("methodName", m.getName()); 241 | root.put("time", new SimpleDateFormat("yyyy年MM月dd日").format(new Date())); 242 | root.put("importlist", importlist); 243 | root.put("pars", pars); 244 | root.put("pars_order", pars_order); 245 | root.put("childlist", childlist); 246 | ArrayList baselist = new ArrayList<>(); 247 | for (Param p : pars) { 248 | if (p.getFather() == null && !baselist.contains(p.getName())) { 249 | baselist.add(p.getName()); 250 | } 251 | } 252 | for (Param p : pars_order) { 253 | if (0 == p.getLayer()) { 254 | baselist.add(p.getName()); 255 | } 256 | } 257 | root.put("baselist", baselist); 258 | Template template; 259 | template = cfg.getTemplate("generateFacadeCase.ftl"); 260 | File f = new File(outFile); 261 | if (!f.exists()) { 262 | f.mkdirs(); 263 | } 264 | String classFile = outFile + className + ".java"; 265 | if (new File(classFile).exists()) { 266 | log.error("该文件已存在,{}", classFile); 267 | throw new Exception("该文件已存在"); 268 | } 269 | PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(classFile))); 270 | template.process(root, out); 271 | System.out.println("更新成功" + classFile); 272 | } catch (Exception e) { 273 | e.printStackTrace(); 274 | } 275 | } 276 | if (0 == time) { 277 | log.info("方法名未找到{}", methodName); 278 | } 279 | } 280 | 281 | 282 | /** 283 | * 取得类所在的参数 284 | * 285 | * @param clazz 286 | * @return 287 | */ 288 | public void addParameter(Class clazz, Param parm, List list) { 289 | List fields = new ArrayList(); 290 | fields = getClassAllFields(clazz, fields); 291 | for (Field f : fields) { 292 | if ("serialVersionUID".equals(f.getName())) { 293 | continue; 294 | } 295 | f.setAccessible(true); 296 | Param par = new Param(); 297 | par.setName(f.getName()); 298 | par.setType(f.getType().getName()); 299 | par.setTypeName(f.getType().getName().split("\\.")[f.getType().getName().split("\\.").length - 1]); 300 | par.setOrder(clazz.getSimpleName()); 301 | par.setLayer(parm.getLayer() + 1); 302 | par.setFather(parm.getName()); 303 | try { 304 | if (isBaseDataType(f.getType())) { 305 | par.setPrimitive("yes"); 306 | } 307 | } catch (Exception e) { 308 | e.printStackTrace(); 309 | } 310 | for (Annotation ann : f.getDeclaredAnnotations()) { 311 | if ("NotBlank".equals(ann.annotationType().getSimpleName()) 312 | || "NotEmpty".equals(ann.annotationType().getSimpleName()) 313 | || "NotNull".equals(ann.annotationType().getSimpleName())) { 314 | par.setAnnotation("NotNull"); 315 | } 316 | } 317 | if (f.getGenericType() instanceof ParameterizedType) { 318 | ParameterizedType pt = (ParameterizedType) f.getGenericType(); 319 | Class clz = (Class) pt.getActualTypeArguments()[0];// 得到对象list中实例的类型 320 | try { 321 | if (!isBaseDataType(clz)) { 322 | par.setChildren(toLowerCaseFirstOne(clz.getName().split("\\.")[clz.getName().split("\\.") 323 | .length - 1])); 324 | par.setChildrenCLass(clz.getName()); 325 | } 326 | } catch (Exception e) { 327 | e.printStackTrace(); 328 | } 329 | } 330 | list.add(par); 331 | } 332 | } 333 | 334 | } 335 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/generate/Param.java: -------------------------------------------------------------------------------- 1 | package com.autotest.generate; 2 | 3 | /** 4 | * Created by huairen on 2017/8/17. 5 | */ 6 | public class Param { 7 | 8 | 9 | /** 参数名*/ 10 | private String name; 11 | 12 | /** 参数名相同时第二参数名*/ 13 | private String secondName; 14 | 15 | /** 参数类型名称*/ 16 | private String typeName; 17 | 18 | /** 参数类型*/ 19 | private String type; 20 | 21 | /** 参数是基本类型*/ 22 | private String primitive; 23 | 24 | /** 参数值*/ 25 | private String value; 26 | 27 | /** 所属order*/ 28 | private String order; 29 | 30 | /** 子参数*/ 31 | private String children; 32 | 33 | /** 参数类名*/ 34 | private String childrenCLass; 35 | 36 | /** 父参数*/ 37 | private String father; 38 | 39 | /** 层级*/ 40 | private int layer; 41 | 42 | /** 备注*/ 43 | private String comment; 44 | 45 | /** 参数对应注解*/ 46 | private String annotation; 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getSecondName() { 57 | return secondName; 58 | } 59 | 60 | public void setSecondName(String secondName) { 61 | this.secondName = secondName; 62 | } 63 | 64 | public String getTypeName() { 65 | return typeName; 66 | } 67 | 68 | public void setTypeName(String typeName) { 69 | this.typeName = typeName; 70 | } 71 | 72 | public String getType() { 73 | return type; 74 | } 75 | 76 | public void setType(String type) { 77 | this.type = type; 78 | } 79 | 80 | public String getPrimitive() { 81 | return primitive; 82 | } 83 | 84 | public void setPrimitive(String primitive) { 85 | this.primitive = primitive; 86 | } 87 | 88 | public String getValue() { 89 | return value; 90 | } 91 | 92 | public void setValue(String value) { 93 | this.value = value; 94 | } 95 | 96 | public String getOrder() { 97 | return order; 98 | } 99 | 100 | public void setOrder(String order) { 101 | this.order = order; 102 | } 103 | 104 | public String getChildren() { 105 | return children; 106 | } 107 | 108 | public void setChildren(String children) { 109 | this.children = children; 110 | } 111 | 112 | public String getChildrenCLass() { 113 | return childrenCLass; 114 | } 115 | 116 | public void setChildrenCLass(String childrenCLass) { 117 | this.childrenCLass = childrenCLass; 118 | } 119 | 120 | public String getFather() { 121 | return father; 122 | } 123 | 124 | public void setFather(String father) { 125 | this.father = father; 126 | } 127 | 128 | public int getLayer() { 129 | return layer; 130 | } 131 | 132 | public void setLayer(int layer) { 133 | this.layer = layer; 134 | } 135 | 136 | public String getComment() { 137 | return comment; 138 | } 139 | 140 | public void setComment(String comment) { 141 | this.comment = comment; 142 | } 143 | 144 | public String getAnnotation() { 145 | return annotation; 146 | } 147 | 148 | public void setAnnotation(String annotation) { 149 | this.annotation = annotation; 150 | } 151 | 152 | @Override 153 | public String toString() { 154 | return "Param [name=" + name + ", secondName=" + secondName + ", typeName=" + typeName + ", type=" + type 155 | + ", primitive=" + primitive + ", value=" + value + ", order=" + order + ", children=" + children 156 | + ", childrenCLass=" + childrenCLass + ", father=" + father + ", layer=" + layer + ", comment=" 157 | + comment + ", annotation=" + annotation + "]"; 158 | } 159 | 160 | } 161 | 162 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/AutoTestMyBatisGenerator.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import com.autotest.generate.GenerateBase; 4 | import org.mybatis.generator.api.GeneratedJavaFile; 5 | import org.mybatis.generator.api.MyBatisGenerator; 6 | import org.mybatis.generator.api.ProgressCallback; 7 | import org.mybatis.generator.api.ShellCallback; 8 | import org.mybatis.generator.config.Configuration; 9 | import org.mybatis.generator.exception.InvalidConfigurationException; 10 | 11 | import java.io.IOException; 12 | import java.sql.SQLException; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | /** 17 | * Created by yu on 17/12/22. 18 | */ 19 | public class AutoTestMyBatisGenerator extends MyBatisGenerator { 20 | 21 | public AutoTestMyBatisGenerator(Configuration configuration, ShellCallback shellCallback, List warnings) 22 | throws InvalidConfigurationException { 23 | super(configuration, shellCallback, warnings); 24 | } 25 | 26 | public void generate(ProgressCallback callback, String projectName) throws SQLException, IOException, 27 | InterruptedException { 28 | super.generate(callback, null, null, true); 29 | List generatedJavaFiles = getGeneratedJavaFiles(); 30 | new GenerateBase().generateBase(projectName, generatedJavaFiles, true); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/Dalgen.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import com.autotest.utils.StringUtils; 4 | import org.mybatis.generator.config.*; 5 | import org.mybatis.generator.internal.DefaultShellCallback; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; 9 | import org.springframework.core.io.ClassPathResource; 10 | 11 | import java.util.*; 12 | 13 | /** 14 | * mybatis代码生成工具 15 | *

16 | * Created by huairen on 2017/8/2. 17 | */ 18 | public class Dalgen { 19 | 20 | private Logger logger = LoggerFactory.getLogger(this.getClass().getName()); 21 | 22 | public static void main(String[] args) { 23 | Dalgen dal = new Dalgen(); 24 | dal.gen("rap"); 25 | } 26 | 27 | public void gen(String projectName) { 28 | if (StringUtils.isBlank(projectName)) { 29 | return; 30 | } 31 | logger.info("开始执行mybatis代码生成工具"); 32 | List warnings = new ArrayList<>(); 33 | /*覆盖原生成的代码*/ 34 | boolean overwrite = true; 35 | try { 36 | YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean(); 37 | yaml.setResources(new ClassPathResource("application.yml")); 38 | Properties prop = yaml.getObject(); 39 | Context context = new Context(ModelType.FLAT); 40 | if (StringUtils.isBlank(prop.getProperty("ds." + projectName + ".url"))) { 41 | logger.info("ds." + projectName + ".url" + "未找到"); 42 | return; 43 | } 44 | JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration(); 45 | jdbcConnectionConfiguration.setDriverClass(prop.getProperty("ds." + projectName + ".driverClassName")); 46 | jdbcConnectionConfiguration.setConnectionURL(prop.getProperty("ds." + projectName + ".url")); 47 | jdbcConnectionConfiguration.setUserId(prop.getProperty("ds." + projectName + ".username")); 48 | jdbcConnectionConfiguration.setPassword(prop.getProperty("ds." + projectName + ".password")); 49 | //生成模型的位置 50 | JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration(); 51 | String tarProject = Dalgen.class.getClassLoader().getResource(".").getFile() 52 | .replace("target/test-classes", "src/main/java") 53 | .replace("target/classes", "src/main/java"); 54 | String name = tarProject.replace("apitest", "core").replace("webtest", "core"); 55 | javaModelGeneratorConfiguration.setTargetProject(name); 56 | javaModelGeneratorConfiguration.setTargetPackage("dal.model." + projectName); 57 | javaModelGeneratorConfiguration.addProperty("enableSubPackages", "true"); 58 | javaModelGeneratorConfiguration.addProperty("trimStrings", "true"); 59 | //生成映射文件的位置 60 | String resourceName = Dalgen.class.getClassLoader().getResource(".").getFile() 61 | .replace("target/test-classes", "src/main/resources") 62 | .replace("target/classes", "src/main/resources"); 63 | String nameResource = resourceName.replace("apitest", "core").replace("webtest", "core"); 64 | SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration(); 65 | sqlMapGeneratorConfiguration.setTargetProject(nameResource); 66 | sqlMapGeneratorConfiguration.setTargetPackage("dal.mapping." + projectName); 67 | sqlMapGeneratorConfiguration.addProperty("enableSubPackages", "true"); 68 | //生成DAO的位置 69 | JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration(); 70 | javaClientGeneratorConfiguration.setTargetProject(name); 71 | javaClientGeneratorConfiguration.setTargetPackage("dal.dao." + projectName); 72 | javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER"); 73 | javaClientGeneratorConfiguration.addProperty("enableSubPackages", "true"); 74 | 75 | PluginConfiguration pluginConfiguration = new PluginConfiguration(); 76 | pluginConfiguration.setConfigurationType("com.autotest.mybatis.ToStringPlugin"); 77 | PluginConfiguration pluginConfiguration1 = new PluginConfiguration(); 78 | pluginConfiguration1.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin"); 79 | PluginConfiguration pluginConfiguration2 = new PluginConfiguration(); 80 | pluginConfiguration2.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin"); 81 | PluginConfiguration pluginConfiguration3 = new PluginConfiguration(); 82 | pluginConfiguration3.setConfigurationType("com.autotest.mybatis.RenameExampleClassPlugin"); 83 | PluginConfiguration pluginConfiguration4 = new PluginConfiguration(); 84 | pluginConfiguration4.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin"); 85 | pluginConfiguration4.addProperty("mappers", "com.autotest.annotation.MyMapper"); 86 | 87 | context.addPluginConfiguration(pluginConfiguration); 88 | context.addPluginConfiguration(pluginConfiguration1); 89 | context.addPluginConfiguration(pluginConfiguration2); 90 | context.addPluginConfiguration(pluginConfiguration3); 91 | context.addPluginConfiguration(pluginConfiguration4); 92 | 93 | context.setId(projectName); 94 | context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration); 95 | context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration); 96 | context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration); 97 | context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration); 98 | String table = prop.getProperty("ds." + projectName + ".tables"); 99 | if (StringUtils.isNotBlank(table)) { 100 | String[] tables = table.split(","); 101 | GeneratedKey generatedKey = new GeneratedKey("id", "MYSQL", true, ""); 102 | Set tabs = new HashSet(Arrays.asList(tables)); 103 | for (String str : tabs) { 104 | if (StringUtils.isBlank(str)) { 105 | continue; 106 | } 107 | TableConfiguration tableConfiguration = new TableConfiguration(context); 108 | tableConfiguration.setTableName(str.trim()); 109 | tableConfiguration.setGeneratedKey(generatedKey); 110 | String column = prop.getProperty("ds." + projectName + ".columnOverride"); 111 | addColumnOverride(tableConfiguration, column); 112 | tableConfiguration.setInsertStatementEnabled(true); 113 | context.addTableConfiguration(tableConfiguration); 114 | } 115 | } else { 116 | TableConfiguration tableConfiguration = new TableConfiguration(context); 117 | tableConfiguration.setTableName("%"); 118 | String column = prop.getProperty("ds." + projectName + ".columnOverride"); 119 | addColumnOverride(tableConfiguration, column); 120 | GeneratedKey generatedKey = new GeneratedKey("id", "MYSQL", true, ""); 121 | tableConfiguration.setGeneratedKey(generatedKey); 122 | context.addTableConfiguration(tableConfiguration); 123 | } 124 | 125 | context.addProperty("beginningDelimiter", "`"); 126 | context.addProperty("endingDelimiter", "`"); 127 | context.addProperty("javaFileEncoding", "UTF-8"); 128 | context.setTargetRuntime("MyBatis3"); 129 | JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration(); 130 | javaTypeResolverConfiguration.addProperty("forceBigDecimals", "false"); 131 | context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration); 132 | 133 | Configuration config = new Configuration(); 134 | config.addContext(context); 135 | config.addClasspathEntry(this.getClass().getClassLoader() 136 | .getResource("lib/mysql-connector-java-5.1.30.jar").getFile()); 137 | DefaultShellCallback callback = new DefaultShellCallback(overwrite); 138 | AutoTestMyBatisGenerator myBatisGenerator = new AutoTestMyBatisGenerator(config, callback, warnings); 139 | myBatisGenerator.generate(null, projectName); 140 | if (warnings.size() != 0) { 141 | logger.info("请注意下面的警告"); 142 | } 143 | for (String warning : warnings) { 144 | logger.info(warning); 145 | } 146 | logger.info("代码生成完成"); 147 | } catch (Exception e) { 148 | e.printStackTrace(); 149 | } 150 | } 151 | 152 | public void addColumnOverride(TableConfiguration tableConfiguration, String column) { 153 | if (StringUtils.isNotBlank(column)) { 154 | String[] columns = column.split(","); 155 | Set cols = new HashSet(Arrays.asList(columns)); 156 | for (String col : cols) { 157 | if (StringUtils.isBlank(col)) { 158 | continue; 159 | } 160 | ColumnOverride columnOverride = new ColumnOverride(col.trim()); 161 | columnOverride.setJdbcType("VARCHAR"); 162 | tableConfiguration.addColumnOverride(columnOverride); 163 | } 164 | } 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/DefaultCommentGenerator.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.Properties; 6 | 7 | import org.mybatis.generator.api.CommentGenerator; 8 | import org.mybatis.generator.api.IntrospectedColumn; 9 | import org.mybatis.generator.api.IntrospectedTable; 10 | import org.mybatis.generator.api.dom.java.*; 11 | import org.mybatis.generator.api.dom.xml.TextElement; 12 | import org.mybatis.generator.api.dom.xml.XmlElement; 13 | import org.mybatis.generator.internal.util.StringUtility; 14 | 15 | /** 16 | * Created by huairen on 2017/8/2. 17 | */ 18 | public class DefaultCommentGenerator implements CommentGenerator { 19 | private Properties properties = new Properties(); 20 | private boolean suppressDate = false; 21 | private boolean suppressAllComments = false; 22 | private boolean addRemarkComments = false; 23 | private SimpleDateFormat dateFormat; 24 | 25 | public DefaultCommentGenerator() { 26 | } 27 | 28 | public void addJavaFileComment(CompilationUnit compilationUnit) { 29 | compilationUnit.addFileCommentLine("/**"); 30 | compilationUnit.addFileCommentLine(" * This class was generated by MyBatis Generator, do not modify."); 31 | compilationUnit.addFileCommentLine(" *"); 32 | compilationUnit.addFileCommentLine(" * @Filename " + 33 | compilationUnit.getType().getShortName() + ".java"); 34 | compilationUnit.addFileCommentLine(" *"); 35 | compilationUnit.addFileCommentLine(" * @Author huairen"); 36 | compilationUnit.addFileCommentLine(" *"); 37 | compilationUnit.addFileCommentLine(" */"); 38 | 39 | } 40 | 41 | public void addComment(XmlElement xmlElement) { 42 | if (!this.suppressAllComments) { 43 | xmlElement.addElement(new TextElement("")); 50 | } 51 | } 52 | 53 | public void addRootComment(XmlElement rootElement) { 54 | // rootElement.addElement(new TextElement("")); 63 | rootElement.addElement(new TextElement("")); 64 | return; 65 | 66 | } 67 | 68 | public void addConfigurationProperties(Properties properties) { 69 | this.properties.putAll(properties); 70 | this.suppressDate = StringUtility.isTrue(properties.getProperty("suppressDate")); 71 | this.suppressAllComments = StringUtility.isTrue(properties.getProperty("suppressAllComments")); 72 | this.addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments")); 73 | String dateFormatString = properties.getProperty("dateFormat"); 74 | if (StringUtility.stringHasValue(dateFormatString)) { 75 | this.dateFormat = new SimpleDateFormat(dateFormatString); 76 | } 77 | 78 | } 79 | 80 | protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { 81 | javaElement.addJavaDocLine(" *"); 82 | StringBuilder sb = new StringBuilder(); 83 | sb.append(" * "); 84 | sb.append("@mbg.generated"); 85 | if (markAsDoNotDelete) { 86 | sb.append(" do_not_delete_during_merge"); 87 | } 88 | // String s = this.getDateString(); 89 | // if(s != null) { 90 | // sb.append(' '); 91 | // sb.append(s); 92 | // } 93 | javaElement.addJavaDocLine(sb.toString()); 94 | } 95 | 96 | protected String getDateString() { 97 | return this.suppressDate ? null : (this.dateFormat != null ? this.dateFormat.format(new Date()) : (new Date()).toString()); 98 | } 99 | 100 | public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { 101 | if (!this.suppressAllComments) { 102 | StringBuilder sb = new StringBuilder(); 103 | innerClass.addJavaDocLine("/**"); 104 | innerClass.addJavaDocLine(" * This class was generated by MyBatis Generator."); 105 | sb.append(" * This class corresponds to the database table "); 106 | sb.append(introspectedTable.getFullyQualifiedTable()); 107 | innerClass.addJavaDocLine(sb.toString()); 108 | this.addJavadocTag(innerClass, false); 109 | innerClass.addJavaDocLine(" */"); 110 | } 111 | } 112 | 113 | public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { 114 | if (!this.suppressAllComments && this.addRemarkComments) { 115 | StringBuilder sb = new StringBuilder(); 116 | topLevelClass.addJavaDocLine("/**"); 117 | String remarks = introspectedTable.getRemarks(); 118 | if (this.addRemarkComments && StringUtility.stringHasValue(remarks)) { 119 | topLevelClass.addJavaDocLine(" * Database Table Remarks:"); 120 | String[] remarkLines = remarks.split(System.getProperty("line.separator")); 121 | String[] var6 = remarkLines; 122 | int var7 = remarkLines.length; 123 | 124 | for (int var8 = 0; var8 < var7; ++var8) { 125 | String remarkLine = var6[var8]; 126 | topLevelClass.addJavaDocLine(" * " + remarkLine); 127 | } 128 | } 129 | 130 | topLevelClass.addJavaDocLine(" *"); 131 | topLevelClass.addJavaDocLine(" * This class was generated by MyBatis Generator."); 132 | sb.append(" * This class corresponds to the database table "); 133 | sb.append(introspectedTable.getFullyQualifiedTable()); 134 | topLevelClass.addJavaDocLine(sb.toString()); 135 | this.addJavadocTag(topLevelClass, true); 136 | topLevelClass.addJavaDocLine(" */"); 137 | } 138 | } 139 | 140 | public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { 141 | if (!this.suppressAllComments) { 142 | StringBuilder sb = new StringBuilder(); 143 | innerEnum.addJavaDocLine("/**"); 144 | innerEnum.addJavaDocLine(" * This enum was generated by MyBatis Generator."); 145 | sb.append(" * This enum corresponds to the database table "); 146 | sb.append(introspectedTable.getFullyQualifiedTable()); 147 | innerEnum.addJavaDocLine(sb.toString()); 148 | this.addJavadocTag(innerEnum, false); 149 | innerEnum.addJavaDocLine(" */"); 150 | } 151 | } 152 | 153 | public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { 154 | if (!this.suppressAllComments) { 155 | field.addJavaDocLine("/**"); 156 | String remarks = introspectedColumn.getRemarks(); 157 | if (this.addRemarkComments && StringUtility.stringHasValue(remarks)) { 158 | field.addJavaDocLine(" * Database Column Remarks:"); 159 | String[] remarkLines = remarks.split(System.getProperty("line.separator")); 160 | String[] var6 = remarkLines; 161 | int var7 = remarkLines.length; 162 | 163 | for (int var8 = 0; var8 < var7; ++var8) { 164 | String remarkLine = var6[var8]; 165 | field.addJavaDocLine(" * " + remarkLine); 166 | } 167 | } 168 | 169 | field.addJavaDocLine(" *"); 170 | field.addJavaDocLine(" * This field was generated by MyBatis Generator."); 171 | StringBuilder sb = new StringBuilder(); 172 | sb.append(" * This field corresponds to the database column "); 173 | sb.append(introspectedTable.getFullyQualifiedTable()); 174 | sb.append('.'); 175 | sb.append(introspectedColumn.getActualColumnName()); 176 | field.addJavaDocLine(sb.toString()); 177 | this.addJavadocTag(field, false); 178 | field.addJavaDocLine(" */"); 179 | } 180 | } 181 | 182 | public void addFieldComment(Field field, IntrospectedTable introspectedTable) { 183 | if (!this.suppressAllComments) { 184 | StringBuilder sb = new StringBuilder(); 185 | field.addJavaDocLine("/**"); 186 | field.addJavaDocLine(" * This field was generated by MyBatis Generator."); 187 | sb.append(" * This field corresponds to the database table "); 188 | sb.append(introspectedTable.getFullyQualifiedTable()); 189 | field.addJavaDocLine(sb.toString()); 190 | this.addJavadocTag(field, false); 191 | field.addJavaDocLine(" */"); 192 | } 193 | } 194 | 195 | public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { 196 | if (!this.suppressAllComments) { 197 | StringBuilder sb = new StringBuilder(); 198 | method.addJavaDocLine("/**"); 199 | method.addJavaDocLine(" * This method was generated by MyBatis Generator."); 200 | sb.append(" * This method corresponds to the database table "); 201 | sb.append(introspectedTable.getFullyQualifiedTable()); 202 | method.addJavaDocLine(sb.toString()); 203 | this.addJavadocTag(method, false); 204 | method.addJavaDocLine(" */"); 205 | } 206 | } 207 | 208 | public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { 209 | if (!this.suppressAllComments) { 210 | StringBuilder sb = new StringBuilder(); 211 | method.addJavaDocLine("/**"); 212 | method.addJavaDocLine(" * This method was generated by MyBatis Generator."); 213 | sb.append(" * This method returns the value of the database column "); 214 | sb.append(introspectedTable.getFullyQualifiedTable()); 215 | sb.append('.'); 216 | sb.append(introspectedColumn.getActualColumnName()); 217 | method.addJavaDocLine(sb.toString()); 218 | method.addJavaDocLine(" *"); 219 | sb.setLength(0); 220 | sb.append(" * @return the value of "); 221 | sb.append(introspectedTable.getFullyQualifiedTable()); 222 | sb.append('.'); 223 | sb.append(introspectedColumn.getActualColumnName()); 224 | method.addJavaDocLine(sb.toString()); 225 | this.addJavadocTag(method, false); 226 | method.addJavaDocLine(" */"); 227 | } 228 | } 229 | 230 | public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { 231 | if (!this.suppressAllComments) { 232 | StringBuilder sb = new StringBuilder(); 233 | method.addJavaDocLine("/**"); 234 | method.addJavaDocLine(" * This method was generated by MyBatis Generator."); 235 | sb.append(" * This method sets the value of the database column "); 236 | sb.append(introspectedTable.getFullyQualifiedTable()); 237 | sb.append('.'); 238 | sb.append(introspectedColumn.getActualColumnName()); 239 | method.addJavaDocLine(sb.toString()); 240 | method.addJavaDocLine(" *"); 241 | Parameter parm = (Parameter) method.getParameters().get(0); 242 | sb.setLength(0); 243 | sb.append(" * @param "); 244 | sb.append(parm.getName()); 245 | sb.append(" the value for "); 246 | sb.append(introspectedTable.getFullyQualifiedTable()); 247 | sb.append('.'); 248 | sb.append(introspectedColumn.getActualColumnName()); 249 | method.addJavaDocLine(sb.toString()); 250 | this.addJavadocTag(method, false); 251 | method.addJavaDocLine(" */"); 252 | } 253 | } 254 | 255 | public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { 256 | if (!this.suppressAllComments) { 257 | StringBuilder sb = new StringBuilder(); 258 | innerClass.addJavaDocLine("/**"); 259 | innerClass.addJavaDocLine(" * This class was generated by MyBatis Generator."); 260 | sb.append(" * This class corresponds to the database table "); 261 | sb.append(introspectedTable.getFullyQualifiedTable()); 262 | innerClass.addJavaDocLine(sb.toString()); 263 | this.addJavadocTag(innerClass, markAsDoNotDelete); 264 | innerClass.addJavaDocLine(" */"); 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/MapperConfigPlugin.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import org.mybatis.generator.api.GeneratedXmlFile; 8 | import org.mybatis.generator.api.IntrospectedTable; 9 | import org.mybatis.generator.api.PluginAdapter; 10 | import org.mybatis.generator.api.dom.xml.Attribute; 11 | import org.mybatis.generator.api.dom.xml.Document; 12 | import org.mybatis.generator.api.dom.xml.TextElement; 13 | import org.mybatis.generator.api.dom.xml.XmlElement; 14 | import org.mybatis.generator.internal.util.StringUtility; 15 | import org.mybatis.generator.internal.util.messages.Messages; 16 | 17 | /** 18 | * Created by huairen on 2017/8/2. 19 | */ 20 | public class MapperConfigPlugin extends PluginAdapter { 21 | private List mapperFiles = new ArrayList(); 22 | 23 | public MapperConfigPlugin() { 24 | } 25 | 26 | @Override 27 | public boolean validate(List warnings) { 28 | boolean valid = true; 29 | if (!StringUtility.stringHasValue(this.properties.getProperty("targetProject"))) { 30 | warnings.add(Messages.getString("ValidationError.18", "MapperConfigPlugin", "targetProject")); 31 | valid = false; 32 | } 33 | 34 | if (!StringUtility.stringHasValue(this.properties.getProperty("targetPackage"))) { 35 | warnings.add(Messages.getString("ValidationError.18", "MapperConfigPlugin", "targetPackage")); 36 | valid = false; 37 | } 38 | 39 | return valid; 40 | } 41 | 42 | @Override 43 | public List contextGenerateAdditionalXmlFiles() { 44 | Document document = new Document("-//mybatis.org//DTD Config 3.0//EN", "http://mybatis.org/dtd/mybatis-3-config.dtd"); 45 | XmlElement root = new XmlElement("configuration"); 46 | document.setRootElement(root); 47 | root.addElement(new TextElement("")); 50 | XmlElement mappers = new XmlElement("mappers"); 51 | root.addElement(mappers); 52 | Iterator var6 = this.mapperFiles.iterator(); 53 | 54 | while (var6.hasNext()) { 55 | String mapperFile = (String) var6.next(); 56 | XmlElement mapper = new XmlElement("mapper"); 57 | mapper.addAttribute(new Attribute("resource", mapperFile)); 58 | mappers.addElement(mapper); 59 | } 60 | 61 | GeneratedXmlFile gxf = new GeneratedXmlFile(document, this.properties.getProperty("fileName", "MapperConfig.xml"), this.properties.getProperty("targetPackage"), this.properties.getProperty("targetProject"), false, this.context.getXmlFormatter()); 62 | List answer = new ArrayList(1); 63 | answer.add(gxf); 64 | return answer; 65 | } 66 | 67 | @Override 68 | public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) { 69 | StringBuilder sb = new StringBuilder(); 70 | sb.append(sqlMap.getTargetPackage()); 71 | sb.append('.'); 72 | String temp = sb.toString(); 73 | sb.setLength(0); 74 | sb.append(temp.replace('.', '/')); 75 | sb.append(sqlMap.getFileName()); 76 | this.mapperFiles.add(sb.toString()); 77 | return true; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/MultiBeanNameGenerator.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import org.springframework.beans.factory.config.BeanDefinition; 4 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 5 | import org.springframework.beans.factory.support.BeanNameGenerator; 6 | 7 | /** 8 | * Created by huairen on 2017/9/6. 9 | */ 10 | public class MultiBeanNameGenerator implements BeanNameGenerator { 11 | 12 | @Override 13 | public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { 14 | return definition.getBeanClassName(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/RenameExampleClassPlugin.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import org.mybatis.generator.api.IntrospectedTable; 4 | import org.mybatis.generator.api.PluginAdapter; 5 | import org.mybatis.generator.internal.util.StringUtility; 6 | import org.mybatis.generator.internal.util.messages.Messages; 7 | 8 | import java.util.List; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | /** 13 | * Created by huairen on 2017/8/2. 14 | */ 15 | public class RenameExampleClassPlugin extends PluginAdapter { 16 | private String searchString; 17 | private String replaceString; 18 | private Pattern pattern; 19 | private boolean valid; 20 | 21 | 22 | public RenameExampleClassPlugin() { 23 | } 24 | 25 | @Override 26 | public boolean validate(List warnings) { 27 | this.searchString = this.properties.getProperty("searchString"); 28 | this.replaceString = this.properties.getProperty("replaceString"); 29 | valid = StringUtility.stringHasValue(this.searchString) && StringUtility.stringHasValue(this.replaceString); 30 | if(valid) { 31 | this.pattern = Pattern.compile(this.searchString); 32 | } else { 33 | // if(!StringUtility.stringHasValue(this.searchString)) { 34 | // warnings.add(Messages.getString("ValidationError.18", "RenameExampleClassPlugin", "searchString")); 35 | // } 36 | // 37 | // if(!StringUtility.stringHasValue(this.replaceString)) { 38 | // warnings.add(Messages.getString("ValidationError.18", "RenameExampleClassPlugin", "replaceString")); 39 | // } 40 | } 41 | 42 | return true; 43 | } 44 | @Override 45 | public void initialized(IntrospectedTable introspectedTable) { 46 | if(valid) { 47 | String oldType = introspectedTable.getExampleType(); 48 | Matcher matcher = this.pattern.matcher(oldType); 49 | oldType = matcher.replaceAll(this.replaceString); 50 | introspectedTable.setExampleType(oldType); 51 | }else { 52 | String oldType = introspectedTable.getBaseRecordType(); 53 | String newType = oldType + "DO"; 54 | introspectedTable.setBaseRecordType(newType); 55 | introspectedTable.setExampleType(newType + "Example"); 56 | String oldMapper = introspectedTable.getMyBatis3JavaMapperType(); 57 | String newMapper = oldMapper.replaceAll("Mapper$", "DAO"); 58 | introspectedTable.setMyBatis3JavaMapperType(newMapper); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/mybatis/ToStringPlugin.java: -------------------------------------------------------------------------------- 1 | package com.autotest.mybatis; 2 | 3 | import org.mybatis.generator.api.IntrospectedTable; 4 | import org.mybatis.generator.api.PluginAdapter; 5 | import org.mybatis.generator.api.dom.java.Field; 6 | import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; 7 | import org.mybatis.generator.api.dom.java.JavaVisibility; 8 | import org.mybatis.generator.api.dom.java.Method; 9 | import org.mybatis.generator.api.dom.java.TopLevelClass; 10 | import org.mybatis.generator.internal.util.StringUtility; 11 | 12 | import java.util.Iterator; 13 | import java.util.List; 14 | import java.util.Properties; 15 | 16 | /** 17 | * Created by huairen on 2017/8/2. 18 | */ 19 | public class ToStringPlugin extends PluginAdapter { 20 | private boolean useToStringFromRoot; 21 | 22 | public ToStringPlugin() { 23 | } 24 | 25 | @Override 26 | public void setProperties(Properties properties) { 27 | super.setProperties(properties); 28 | this.useToStringFromRoot = StringUtility.isTrue(properties.getProperty("useToStringFromRoot")); 29 | } 30 | 31 | @Override 32 | public boolean validate(List warnings) { 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { 38 | this.generateToString(introspectedTable, topLevelClass); 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { 44 | this.generateToString(introspectedTable, topLevelClass); 45 | return true; 46 | } 47 | 48 | @Override 49 | public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { 50 | this.generateToString(introspectedTable, topLevelClass); 51 | return true; 52 | } 53 | 54 | private void generateToString(IntrospectedTable introspectedTable, TopLevelClass topLevelClass) { 55 | Method method = new Method(); 56 | method.setVisibility(JavaVisibility.PUBLIC); 57 | method.setReturnType(FullyQualifiedJavaType.getStringInstance()); 58 | method.setName("toString"); 59 | if(introspectedTable.isJava5Targeted()) { 60 | method.addAnnotation("@Override"); 61 | } 62 | 63 | this.context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable); 64 | method.addBodyLine("StringBuilder sb = new StringBuilder();"); 65 | method.addBodyLine("sb.append(getClass().getSimpleName());"); 66 | method.addBodyLine("sb.append(\" [\");"); 67 | StringBuilder sb = new StringBuilder(); 68 | Iterator var5 = topLevelClass.getFields().iterator(); 69 | 70 | while(var5.hasNext()) { 71 | Field field = (Field)var5.next(); 72 | String property = field.getName(); 73 | sb.setLength(0); 74 | sb.append("sb.append(\"").append(", ").append(property).append("=\")").append(".append(").append(property).append(");"); 75 | method.addBodyLine(sb.toString()); 76 | } 77 | 78 | method.addBodyLine("sb.append(\"]\");"); 79 | 80 | method.addBodyLine("return sb.toString();"); 81 | topLevelClass.addMethod(method); 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/utils/HttpClient.java: -------------------------------------------------------------------------------- 1 | package com.autotest.utils; 2 | 3 | import org.apache.http.client.methods.CloseableHttpResponse; 4 | import org.apache.http.client.methods.HttpGet; 5 | import org.apache.http.client.methods.HttpPost; 6 | import org.apache.http.entity.StringEntity; 7 | import org.apache.http.impl.client.CloseableHttpClient; 8 | import org.apache.http.impl.client.HttpClients; 9 | import org.apache.http.util.EntityUtils; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * Created by huairen on 2017/8/21. 15 | */ 16 | public class HttpClient { 17 | 18 | /** 19 | * 发送get请求,返回内容字符串 20 | */ 21 | public static String doGet(String url) { 22 | String result = null; 23 | HttpGet httpGet = new HttpGet(url); 24 | CloseableHttpClient httpclient = HttpClients.createDefault(); 25 | try { 26 | CloseableHttpResponse response = httpclient.execute(httpGet); 27 | if (response.getStatusLine().getStatusCode() == 200) { 28 | result = EntityUtils.toString(response.getEntity(), "UTF-8"); 29 | } 30 | response.close(); 31 | } catch (IOException e) { 32 | e.printStackTrace(); 33 | } 34 | return result; 35 | } 36 | /** 37 | * 发送get请求,返回response 38 | */ 39 | public static CloseableHttpResponse httpGet(String url) { 40 | HttpGet httpGet = new HttpGet(url); 41 | CloseableHttpClient httpclient = HttpClients.createDefault(); 42 | CloseableHttpResponse response = null; 43 | try { 44 | response = httpclient.execute(httpGet); 45 | response.close(); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | return response; 50 | } 51 | 52 | public static CloseableHttpResponse httpPost(String data,String url) { 53 | HttpPost httpPost = new HttpPost(url); 54 | httpPost.setEntity(new StringEntity(data,"UTF-8")); 55 | CloseableHttpClient httpclient = HttpClients.createDefault(); 56 | CloseableHttpResponse response = null; 57 | try { 58 | response = httpclient.execute(httpPost); 59 | response.close(); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | return response; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/utils/ProcessObject.java: -------------------------------------------------------------------------------- 1 | package com.autotest.utils; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | import org.apache.log4j.Logger; 9 | 10 | import javassist.Modifier; 11 | 12 | 13 | public class ProcessObject { 14 | private static final Logger logger = Logger.getLogger(ProcessObject.class); 15 | 16 | public static Object processing(Class cl, String con) { 17 | Object o = null; 18 | String fieldType = cl.getName(); 19 | try { 20 | if (String.class.getName().equals(fieldType)) { 21 | return con; 22 | } else if (Integer.class.getName().equals(fieldType) || "int".equals(fieldType)) { 23 | if (StringUtils.isBlank(con)) { 24 | con = "0"; 25 | } 26 | o = Integer.parseInt(con); 27 | return o; 28 | } else if (Short.class.getName().equals(fieldType) || "short".equals(fieldType)) { 29 | if (StringUtils.isBlank(con)) { 30 | con = "0"; 31 | } 32 | o = Short.parseShort(con); 33 | return o; 34 | } else if (Character.class.getName().equals(fieldType) || "char".equals(fieldType)) { 35 | if (StringUtils.isBlank(con)) { 36 | con = "0"; 37 | } 38 | o = con.charAt(0); 39 | return o; 40 | } else if (Byte.class.getName().equals(fieldType) || "byte".equals(fieldType)) { 41 | if (StringUtils.isBlank(con)) { 42 | con = "0"; 43 | } 44 | o = con.getBytes()[0]; 45 | return o; 46 | } else if (Long.class.getName().equals(fieldType) || "long".equals(fieldType)) { 47 | if (StringUtils.isBlank(con)) { 48 | con = "0"; 49 | } 50 | o = Long.parseLong(con); 51 | return o; 52 | } else if (Double.class.getName().equals(fieldType) || "double".equals(fieldType)) { 53 | if (StringUtils.isBlank(con)) { 54 | con = "0"; 55 | } 56 | o = Double.parseDouble(con); 57 | return o; 58 | } else if (Boolean.class.getName().equals(fieldType) || "boolean".equals(fieldType)) { 59 | o = Boolean.parseBoolean(con); 60 | return o; 61 | } else if (Float.class.getName().equals(fieldType) || "float".equals(fieldType)) { 62 | if (StringUtils.isBlank(con)) { 63 | con = "0"; 64 | } 65 | o = Float.parseFloat(con); 66 | return o; 67 | } else if ((cl.getModifiers() & Modifier.ENUM) != 0) { 68 | if (StringUtils.isNotBlank(con)) { 69 | o = Enum.valueOf(cl, con); 70 | } 71 | return o; 72 | } else if (ArrayList.class.getName().equals(fieldType)) { 73 | String[] strs = con.split("#"); 74 | List ls = new ArrayList(); 75 | for (String str : strs) { 76 | ls.add(str); 77 | } 78 | o = ls; 79 | return o; 80 | } else if (Date.class.getName().equals(fieldType)) { 81 | if (StringUtils.isBlank(con)) { 82 | return null; 83 | } 84 | return new Class[0]; 85 | } else if (BigDecimal.class.getName().equals(fieldType)) { 86 | if (StringUtils.isBlank(con)) { 87 | return null; 88 | } 89 | o = new BigDecimal(con); 90 | return o; 91 | } else { 92 | o = StringUtils.isBlank(con) ? null : con; 93 | } 94 | } catch (RuntimeException e) { 95 | logger.error("参数类型:" + fieldType + " 不能转换,参数值为:" + con); 96 | throw e; 97 | } 98 | 99 | return o; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/utils/PropertyUtil.java: -------------------------------------------------------------------------------- 1 | package com.autotest.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.*; 7 | import java.util.Properties; 8 | /** 9 | * @author huairen 10 | * Created on 18/1/25. 11 | */ 12 | public class PropertyUtil { 13 | private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class); 14 | private static Properties props; 15 | static{ 16 | loadProps(); 17 | } 18 | 19 | synchronized static private void loadProps(){ 20 | logger.info("开始加载properties文件内容......."); 21 | props = new Properties(); 22 | InputStream in = null; 23 | try { 24 | in = PropertyUtil.class.getClassLoader().getResourceAsStream("application.properties"); 25 | props.load(in); 26 | } catch (FileNotFoundException e) { 27 | logger.error("jdbc.properties文件未找到"); 28 | } catch (IOException e) { 29 | logger.error("出现IOException"); 30 | } finally { 31 | try { 32 | if(null != in) { 33 | in.close(); 34 | } 35 | } catch (IOException e) { 36 | logger.error("jdbc.properties文件流关闭出现异常"); 37 | } 38 | } 39 | logger.info("加载properties文件内容完成..........."); 40 | } 41 | 42 | public static String getProperty(String key){ 43 | if(null == props) { 44 | loadProps(); 45 | } 46 | return props.getProperty(key); 47 | } 48 | 49 | public static String getProperty(String key, String defaultValue) { 50 | if(null == props) { 51 | loadProps(); 52 | } 53 | return props.getProperty(key, defaultValue); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/autotest/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.autotest.utils; 2 | 3 | /** 4 | * Created by yu on 17/11/15. 5 | */ 6 | public class StringUtils { 7 | 8 | public static boolean isBlank(String str) { 9 | return str == null || str.trim().isEmpty(); 10 | } 11 | 12 | public static boolean isNotBlank(String str) { 13 | return !isBlank(str); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dal/dao/school/StudentDAO.java: -------------------------------------------------------------------------------- 1 | package dal.dao.school; 2 | 3 | import com.autotest.annotation.MyMapper; 4 | import dal.model.school.StudentDO; 5 | import dal.model.school.StudentDOExample; 6 | import java.util.List; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | public interface StudentDAO extends MyMapper { 10 | long countByExample(StudentDOExample example); 11 | 12 | int deleteByExample(StudentDOExample example); 13 | 14 | List selectByExample(StudentDOExample example); 15 | 16 | int updateByExampleSelective(@Param("record") StudentDO record, @Param("example") StudentDOExample example); 17 | 18 | int updateByExample(@Param("record") StudentDO record, @Param("example") StudentDOExample example); 19 | } -------------------------------------------------------------------------------- /src/main/java/dal/model/school/StudentDO.java: -------------------------------------------------------------------------------- 1 | package dal.model.school; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.*; 5 | 6 | @Table(name = "student") 7 | public class StudentDO implements Serializable { 8 | /** 9 | * id 10 | */ 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private Long id; 14 | 15 | /** 16 | * 名称 17 | */ 18 | private String name; 19 | 20 | /** 21 | * 年龄 22 | */ 23 | private Integer age; 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | /** 28 | * 获取id 29 | * 30 | * @return id - id 31 | */ 32 | public Long getId() { 33 | return id; 34 | } 35 | 36 | /** 37 | * 设置id 38 | * 39 | * @param id id 40 | */ 41 | public void setId(Long id) { 42 | this.id = id; 43 | } 44 | 45 | /** 46 | * 获取名称 47 | * 48 | * @return name - 名称 49 | */ 50 | public String getName() { 51 | return name; 52 | } 53 | 54 | /** 55 | * 设置名称 56 | * 57 | * @param name 名称 58 | */ 59 | public void setName(String name) { 60 | this.name = name == null ? null : name.trim(); 61 | } 62 | 63 | /** 64 | * 获取年龄 65 | * 66 | * @return age - 年龄 67 | */ 68 | public Integer getAge() { 69 | return age; 70 | } 71 | 72 | /** 73 | * 设置年龄 74 | * 75 | * @param age 年龄 76 | */ 77 | public void setAge(Integer age) { 78 | this.age = age; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | StringBuilder sb = new StringBuilder(); 84 | sb.append(getClass().getSimpleName()); 85 | sb.append(" ["); 86 | sb.append(", id=").append(id); 87 | sb.append(", name=").append(name); 88 | sb.append(", age=").append(age); 89 | sb.append("]"); 90 | return sb.toString(); 91 | } 92 | 93 | @Override 94 | public boolean equals(Object that) { 95 | if (this == that) { 96 | return true; 97 | } 98 | if (that == null) { 99 | return false; 100 | } 101 | if (getClass() != that.getClass()) { 102 | return false; 103 | } 104 | StudentDO other = (StudentDO) that; 105 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 106 | && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) 107 | && (this.getAge() == null ? other.getAge() == null : this.getAge().equals(other.getAge())); 108 | } 109 | 110 | @Override 111 | public int hashCode() { 112 | final int prime = 31; 113 | int result = 1; 114 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 115 | result = prime * result + ((getName() == null) ? 0 : getName().hashCode()); 116 | result = prime * result + ((getAge() == null) ? 0 : getAge().hashCode()); 117 | return result; 118 | } 119 | } -------------------------------------------------------------------------------- /src/main/java/dal/model/school/StudentDOExample.java: -------------------------------------------------------------------------------- 1 | package dal.model.school; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class StudentDOExample { 7 | protected String orderByClause; 8 | 9 | protected boolean distinct; 10 | 11 | protected List oredCriteria; 12 | 13 | public StudentDOExample() { 14 | oredCriteria = new ArrayList(); 15 | } 16 | 17 | public void setOrderByClause(String orderByClause) { 18 | this.orderByClause = orderByClause; 19 | } 20 | 21 | public String getOrderByClause() { 22 | return orderByClause; 23 | } 24 | 25 | public void setDistinct(boolean distinct) { 26 | this.distinct = distinct; 27 | } 28 | 29 | public boolean isDistinct() { 30 | return distinct; 31 | } 32 | 33 | public List getOredCriteria() { 34 | return oredCriteria; 35 | } 36 | 37 | public void or(Criteria criteria) { 38 | oredCriteria.add(criteria); 39 | } 40 | 41 | public Criteria or() { 42 | Criteria criteria = createCriteriaInternal(); 43 | oredCriteria.add(criteria); 44 | return criteria; 45 | } 46 | 47 | public Criteria createCriteria() { 48 | Criteria criteria = createCriteriaInternal(); 49 | if (oredCriteria.size() == 0) { 50 | oredCriteria.add(criteria); 51 | } 52 | return criteria; 53 | } 54 | 55 | protected Criteria createCriteriaInternal() { 56 | Criteria criteria = new Criteria(); 57 | return criteria; 58 | } 59 | 60 | public void clear() { 61 | oredCriteria.clear(); 62 | orderByClause = null; 63 | distinct = false; 64 | } 65 | 66 | protected abstract static class GeneratedCriteria { 67 | protected List criteria; 68 | 69 | protected GeneratedCriteria() { 70 | super(); 71 | criteria = new ArrayList(); 72 | } 73 | 74 | public boolean isValid() { 75 | return criteria.size() > 0; 76 | } 77 | 78 | public List getAllCriteria() { 79 | return criteria; 80 | } 81 | 82 | public List getCriteria() { 83 | return criteria; 84 | } 85 | 86 | protected void addCriterion(String condition) { 87 | if (condition == null) { 88 | throw new RuntimeException("Value for condition cannot be null"); 89 | } 90 | criteria.add(new Criterion(condition)); 91 | } 92 | 93 | protected void addCriterion(String condition, Object value, String property) { 94 | if (value == null) { 95 | throw new RuntimeException("Value for " + property + " cannot be null"); 96 | } 97 | criteria.add(new Criterion(condition, value)); 98 | } 99 | 100 | protected void addCriterion(String condition, Object value1, Object value2, String property) { 101 | if (value1 == null || value2 == null) { 102 | throw new RuntimeException("Between values for " + property + " cannot be null"); 103 | } 104 | criteria.add(new Criterion(condition, value1, value2)); 105 | } 106 | 107 | public Criteria andIdIsNull() { 108 | addCriterion("id is null"); 109 | return (Criteria) this; 110 | } 111 | 112 | public Criteria andIdIsNotNull() { 113 | addCriterion("id is not null"); 114 | return (Criteria) this; 115 | } 116 | 117 | public Criteria andIdEqualTo(Long value) { 118 | addCriterion("id =", value, "id"); 119 | return (Criteria) this; 120 | } 121 | 122 | public Criteria andIdNotEqualTo(Long value) { 123 | addCriterion("id <>", value, "id"); 124 | return (Criteria) this; 125 | } 126 | 127 | public Criteria andIdGreaterThan(Long value) { 128 | addCriterion("id >", value, "id"); 129 | return (Criteria) this; 130 | } 131 | 132 | public Criteria andIdGreaterThanOrEqualTo(Long value) { 133 | addCriterion("id >=", value, "id"); 134 | return (Criteria) this; 135 | } 136 | 137 | public Criteria andIdLessThan(Long value) { 138 | addCriterion("id <", value, "id"); 139 | return (Criteria) this; 140 | } 141 | 142 | public Criteria andIdLessThanOrEqualTo(Long value) { 143 | addCriterion("id <=", value, "id"); 144 | return (Criteria) this; 145 | } 146 | 147 | public Criteria andIdIn(List values) { 148 | addCriterion("id in", values, "id"); 149 | return (Criteria) this; 150 | } 151 | 152 | public Criteria andIdNotIn(List values) { 153 | addCriterion("id not in", values, "id"); 154 | return (Criteria) this; 155 | } 156 | 157 | public Criteria andIdBetween(Long value1, Long value2) { 158 | addCriterion("id between", value1, value2, "id"); 159 | return (Criteria) this; 160 | } 161 | 162 | public Criteria andIdNotBetween(Long value1, Long value2) { 163 | addCriterion("id not between", value1, value2, "id"); 164 | return (Criteria) this; 165 | } 166 | 167 | public Criteria andNameIsNull() { 168 | addCriterion("name is null"); 169 | return (Criteria) this; 170 | } 171 | 172 | public Criteria andNameIsNotNull() { 173 | addCriterion("name is not null"); 174 | return (Criteria) this; 175 | } 176 | 177 | public Criteria andNameEqualTo(String value) { 178 | addCriterion("name =", value, "name"); 179 | return (Criteria) this; 180 | } 181 | 182 | public Criteria andNameNotEqualTo(String value) { 183 | addCriterion("name <>", value, "name"); 184 | return (Criteria) this; 185 | } 186 | 187 | public Criteria andNameGreaterThan(String value) { 188 | addCriterion("name >", value, "name"); 189 | return (Criteria) this; 190 | } 191 | 192 | public Criteria andNameGreaterThanOrEqualTo(String value) { 193 | addCriterion("name >=", value, "name"); 194 | return (Criteria) this; 195 | } 196 | 197 | public Criteria andNameLessThan(String value) { 198 | addCriterion("name <", value, "name"); 199 | return (Criteria) this; 200 | } 201 | 202 | public Criteria andNameLessThanOrEqualTo(String value) { 203 | addCriterion("name <=", value, "name"); 204 | return (Criteria) this; 205 | } 206 | 207 | public Criteria andNameLike(String value) { 208 | addCriterion("name like", value, "name"); 209 | return (Criteria) this; 210 | } 211 | 212 | public Criteria andNameNotLike(String value) { 213 | addCriterion("name not like", value, "name"); 214 | return (Criteria) this; 215 | } 216 | 217 | public Criteria andNameIn(List values) { 218 | addCriterion("name in", values, "name"); 219 | return (Criteria) this; 220 | } 221 | 222 | public Criteria andNameNotIn(List values) { 223 | addCriterion("name not in", values, "name"); 224 | return (Criteria) this; 225 | } 226 | 227 | public Criteria andNameBetween(String value1, String value2) { 228 | addCriterion("name between", value1, value2, "name"); 229 | return (Criteria) this; 230 | } 231 | 232 | public Criteria andNameNotBetween(String value1, String value2) { 233 | addCriterion("name not between", value1, value2, "name"); 234 | return (Criteria) this; 235 | } 236 | 237 | public Criteria andAgeIsNull() { 238 | addCriterion("age is null"); 239 | return (Criteria) this; 240 | } 241 | 242 | public Criteria andAgeIsNotNull() { 243 | addCriterion("age is not null"); 244 | return (Criteria) this; 245 | } 246 | 247 | public Criteria andAgeEqualTo(Integer value) { 248 | addCriterion("age =", value, "age"); 249 | return (Criteria) this; 250 | } 251 | 252 | public Criteria andAgeNotEqualTo(Integer value) { 253 | addCriterion("age <>", value, "age"); 254 | return (Criteria) this; 255 | } 256 | 257 | public Criteria andAgeGreaterThan(Integer value) { 258 | addCriterion("age >", value, "age"); 259 | return (Criteria) this; 260 | } 261 | 262 | public Criteria andAgeGreaterThanOrEqualTo(Integer value) { 263 | addCriterion("age >=", value, "age"); 264 | return (Criteria) this; 265 | } 266 | 267 | public Criteria andAgeLessThan(Integer value) { 268 | addCriterion("age <", value, "age"); 269 | return (Criteria) this; 270 | } 271 | 272 | public Criteria andAgeLessThanOrEqualTo(Integer value) { 273 | addCriterion("age <=", value, "age"); 274 | return (Criteria) this; 275 | } 276 | 277 | public Criteria andAgeIn(List values) { 278 | addCriterion("age in", values, "age"); 279 | return (Criteria) this; 280 | } 281 | 282 | public Criteria andAgeNotIn(List values) { 283 | addCriterion("age not in", values, "age"); 284 | return (Criteria) this; 285 | } 286 | 287 | public Criteria andAgeBetween(Integer value1, Integer value2) { 288 | addCriterion("age between", value1, value2, "age"); 289 | return (Criteria) this; 290 | } 291 | 292 | public Criteria andAgeNotBetween(Integer value1, Integer value2) { 293 | addCriterion("age not between", value1, value2, "age"); 294 | return (Criteria) this; 295 | } 296 | } 297 | 298 | public static class Criteria extends GeneratedCriteria { 299 | 300 | protected Criteria() { 301 | super(); 302 | } 303 | } 304 | 305 | public static class Criterion { 306 | private String condition; 307 | 308 | private Object value; 309 | 310 | private Object secondValue; 311 | 312 | private boolean noValue; 313 | 314 | private boolean singleValue; 315 | 316 | private boolean betweenValue; 317 | 318 | private boolean listValue; 319 | 320 | private String typeHandler; 321 | 322 | public String getCondition() { 323 | return condition; 324 | } 325 | 326 | public Object getValue() { 327 | return value; 328 | } 329 | 330 | public Object getSecondValue() { 331 | return secondValue; 332 | } 333 | 334 | public boolean isNoValue() { 335 | return noValue; 336 | } 337 | 338 | public boolean isSingleValue() { 339 | return singleValue; 340 | } 341 | 342 | public boolean isBetweenValue() { 343 | return betweenValue; 344 | } 345 | 346 | public boolean isListValue() { 347 | return listValue; 348 | } 349 | 350 | public String getTypeHandler() { 351 | return typeHandler; 352 | } 353 | 354 | protected Criterion(String condition) { 355 | super(); 356 | this.condition = condition; 357 | this.typeHandler = null; 358 | this.noValue = true; 359 | } 360 | 361 | protected Criterion(String condition, Object value, String typeHandler) { 362 | super(); 363 | this.condition = condition; 364 | this.value = value; 365 | this.typeHandler = typeHandler; 366 | if (value instanceof List) { 367 | this.listValue = true; 368 | } else { 369 | this.singleValue = true; 370 | } 371 | } 372 | 373 | protected Criterion(String condition, Object value) { 374 | this(condition, value, null); 375 | } 376 | 377 | protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { 378 | super(); 379 | this.condition = condition; 380 | this.value = value; 381 | this.secondValue = secondValue; 382 | this.typeHandler = typeHandler; 383 | this.betweenValue = true; 384 | } 385 | 386 | protected Criterion(String condition, Object value, Object secondValue) { 387 | this(condition, value, secondValue, null); 388 | } 389 | } 390 | } -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | #Dubbo 服务消费者配置 3 | dubbo: 4 | application: 5 | name: autotest 6 | registries[0]: 7 | address: zookeeper://192.168.2.223:2181 8 | timeout: 60000 9 | scan: com.autotest 10 | #数据库配置 11 | ds: 12 | #default 13 | default: 14 | url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=true 15 | username: root 16 | password: 123456 17 | driverClassName: com.mysql.jdbc.Driver 18 | #school 19 | school: 20 | url: jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=true 21 | username: root 22 | password: 123456 23 | driverClassName: com.mysql.jdbc.Driver 24 | tables: student 25 | -------------------------------------------------------------------------------- /src/main/resources/dal/mapping/school/StudentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | and ${criterion.condition} 24 | 25 | 26 | and ${criterion.condition} #{criterion.value} 27 | 28 | 29 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 30 | 31 | 32 | and ${criterion.condition} 33 | 34 | #{listItem} 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | and ${criterion.condition} 56 | 57 | 58 | and ${criterion.condition} #{criterion.value} 59 | 60 | 61 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 62 | 63 | 64 | and ${criterion.condition} 65 | 66 | #{listItem} 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | id, name, age 81 | 82 | 99 | 100 | 103 | delete from student 104 | 105 | 106 | 107 | 108 | 117 | 118 | 121 | update student 122 | 123 | 124 | id = #{record.id,jdbcType=BIGINT}, 125 | 126 | 127 | name = #{record.name,jdbcType=VARCHAR}, 128 | 129 | 130 | age = #{record.age,jdbcType=INTEGER}, 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 141 | update student 142 | set id = #{record.id,jdbcType=BIGINT}, 143 | name = #{record.name,jdbcType=VARCHAR}, 144 | age = #{record.age,jdbcType=INTEGER} 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /src/main/resources/ftl/generateDataSourceConfig.ftl: -------------------------------------------------------------------------------- 1 | package com.autotest.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.autotest.mybatis.MultiBeanNameGenerator; 5 | import org.apache.ibatis.session.SqlSessionFactory; 6 | import org.mybatis.spring.SqlSessionFactoryBean; 7 | import tk.mybatis.spring.annotation.MapperScan; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 13 | import javax.sql.DataSource; 14 | 15 | @Configuration 16 | @MapperScan(basePackages = "dal.dao.${projectName}", sqlSessionFactoryRef = "${projectName}SqlSessionFactory", nameGenerator = 17 | MultiBeanNameGenerator.class) 18 | public class ${className} extends DruidBaseConfig { 19 | 20 | @Value("${r"${"}ds.${projectName}.url}") 21 | private String url; 22 | 23 | @Value("${r"${"}ds.${projectName}.username}") 24 | private String username; 25 | 26 | @Value("${r"${"}ds.${projectName}.password}") 27 | private String password; 28 | 29 | @Value("${r"${"}ds.${projectName}.driverClassName}") 30 | private String driverClassName; 31 | 32 | @Bean(name = "${projectName}DataSource") 33 | public DataSource ${projectName}DataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | return setDataSource(dataSource, url, username, password, driverClassName); 36 | } 37 | 38 | @Bean(name = "${projectName}TransactionManager") 39 | public DataSourceTransactionManager ${projectName}TransactionManager() { 40 | return new DataSourceTransactionManager(${projectName}DataSource()); 41 | } 42 | 43 | @Bean(name = "${projectName}SqlSessionFactory") 44 | public SqlSessionFactory ${projectName}SqlSessionFactory(@Qualifier("${projectName}DataSource") DataSource ${projectName}DataSource) 45 | throws Exception { 46 | final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 47 | sessionFactory.setDataSource(${projectName}DataSource); 48 | return sessionFactory.getObject(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/resources/ftl/generateFacadeCase.ftl: -------------------------------------------------------------------------------- 1 | package ${packageName}; 2 | 3 | import com.autotest.base.SpringBootTestBase; 4 | import com.autotest.annotation.AutoTest; 5 | import org.junit.jupiter.api.DisplayName; 6 | import com.alibaba.dubbo.config.annotation.Reference; 7 | import java.util.Date; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import ${resultType}; 11 | import ${facadeType}; 12 | <#list importlist as im> 13 | import ${im}; 14 | 15 | 16 | 17 | 18 | /** 19 | * @author ${author!'huairen'} 20 | * Created on ${time}. 21 | */ 22 | public class ${className} extends SpringBootTestBase{ 23 | 24 | @Reference(version = "1.0") 25 | ${facadeName} ${facadeName?uncap_first}; 26 | 27 | @AutoTest(file = "${projectName}/${funcName}Success.csv") 28 | public void ${funcName}Success( 29 | // 基本参数 30 | int testId, 31 | // 业务参数 32 | <#list childlist as child> 33 | <#if child ??> 34 | <#list pars as parm> 35 | <#if 0 == parm.layer> 36 | ${parm.typeName} ${parm.name}<#if (child_has_next)>, 37 | 38 | 39 | 40 | 41 | <#list pars_order as parm> 42 | ${parm.typeName} ${parm.name}<#if (parm_has_next)>, 43 | 44 | ) { 45 | // 清除数据 46 | // 准备数据 47 | // 测试过程 48 | <#--次子订单--> 49 | <#list pars as parm> 50 | <#if 2 == parm.layer> 51 | <#if "List" ==parm.typeName> 52 | <#list pars_order as p> 53 | <#if p.name == parm.children> 54 | List<${p.name?cap_first}> ${parm.secondName} = new ArrayList<${p.name?cap_first}>(); 55 | ${parm.name}.add(${parm.children}); 56 | 57 | 58 | 59 | <#if "Map" == parm.typeName> 60 | Map ${parm.name} = new HashMap<>(); 61 | 62 | 63 | 64 | <#--子订单--> 65 | <#list pars as parm> 66 | <#if 1 == parm.layer> 67 | <#if "List" ==parm.typeName> 68 | <#list pars_order as p> 69 | <#if p.name == parm.children> 70 | List<${p.name?cap_first}> ${parm.secondName} = new ArrayList<${p.name?cap_first}>(); 71 | ${parm.name}.add(${parm.children}); 72 | 73 | 74 | 75 | <#if "Map" == parm.typeName> 76 | Map ${parm.name} = new HashMap<>(); 77 | 78 | 79 | 80 | <#--主订单--> 81 | <#list pars_order as parm> 82 | <#if 0 == parm.layer> 83 | <#list pars_order as par> 84 | <#if 1 == par.layer> 85 | ${parm.name}.set${par.name?cap_first}(${par.name}); 86 | 87 | 88 | 89 | 90 | // 调用接口 91 | ${resultName} result = ${facadeName?uncap_first}.${methodName}(<#list baselist as base>${base}<#if (base_has_next)>,); 92 | // 结果验证 93 | // 数据验证 94 | <#-- 95 | --> 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/resources/ftl/generateTestBase.ftl: -------------------------------------------------------------------------------- 1 | package ${packageName}; 2 | 3 | import java.util.List; 4 | import java.util.Date; 5 | import org.junit.platform.commons.util.StringUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | import java.math.BigDecimal; 9 | import dal.dao.${projectName}.*; 10 | import dal.model.${projectName}.*; 11 | 12 | /** 13 | * @author ${author!'huairen'} 14 | * Created on ${time}. 15 | */ 16 | @Service 17 | public class ${className} { 18 | <#list tableList as table> 19 | 20 | @Autowired 21 | ${table.tableName}DAO ${table.tableName?uncap_first}DAO; 22 | 23 | 24 | <#list tableList as table> 25 | <#--insert插入方法--> 26 | /** 27 | * 插入${table.table}表数据 28 | */ 29 | public void insert${table.tableName}(${table.tableName}DO ${table.tableName?uncap_first}DO) { 30 | ${table.tableName?uncap_first}DAO.insert(${table.tableName?uncap_first}DO); 31 | } 32 | 33 | <#--insert插入方法--> 34 | /** 35 | * 插入${table.table}表数据 36 | */ 37 | public void insert${table.tableName}( 38 | <#list table.pars as par> 39 | ${par.typeName} ${par.name}<#if (par_has_next)>, 40 | 41 | ) { 42 | <#list table.pars as par> 43 | <#if "Date"==par.typeName> 44 | if (${par.name} == null) { 45 | ${par.name} = new Date(); 46 | } 47 | 48 | <#if "Money"==par.typeName> 49 | if (${par.name} == null) { 50 | ${par.name} = new Money(0); 51 | } 52 | 53 | 54 | ${table.tableName}DO ${table.tableName?uncap_first}DO = new ${table.tableName}DO(); 55 | <#list table.pars as par> 56 | <#if par.annotation ??> 57 | ${table.tableName?uncap_first}DO.set${par.name}(${par.name}); 58 | <#else> 59 | ${table.tableName?uncap_first}DO.set${par.name?cap_first}(${par.name}); 60 | 61 | 62 | ${table.tableName?uncap_first}DAO.insert(${table.tableName?uncap_first}DO); 63 | } 64 | 65 | <#list table.pars as par> 66 | <#if par.name?index_of("versionId")!=-1> 67 | <#continue> 68 | 69 | <#if par.name?index_of("Id")!=-1 || par.name?index_of("id")!=-1> 70 | 71 | /** 72 | * 根据${par.name}删除${table.table}表数据 73 | */ 74 | public void clean${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 75 | <#if "Date"==par.typeName> 76 | if (${par.name} == null) { 77 | ${par.name} = new Date(); 78 | } 79 | 80 | <#if "Money"==par.typeName> 81 | if (${par.name} == null) { 82 | ${par.name} = new Money(0); 83 | } 84 | 85 | <#if "String"==par.typeName> 86 | if (StringUtils.isBlank(${par.name})){ 87 | ${par.name} = "test_${par.name}"; 88 | } 89 | 90 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 91 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 92 | ${table.tableName?uncap_first}DAO.deleteByExample(exam); 93 | } 94 | 95 | <#if par.name?index_of("No")!=-1 || par.name?index_of("loginAccount")!=-1> 96 | 97 | /** 98 | * 根据${par.name}删除${table.table}表数据 99 | */ 100 | public void clean${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 101 | <#if "Date"==par.typeName> 102 | if (${par.name} == null) { 103 | ${par.name} = new Date(); 104 | } 105 | 106 | <#if "Money"==par.typeName> 107 | if (${par.name} == null) { 108 | ${par.name} = new Money(0); 109 | } 110 | 111 | <#if "String"==par.typeName> 112 | if (StringUtils.isBlank(${par.name})){ 113 | ${par.name} = "test_${par.name}"; 114 | } 115 | 116 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 117 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 118 | ${table.tableName?uncap_first}DAO.deleteByExample(exam); 119 | } 120 | 121 | <#if par.name?index_of("Name")!=-1 || par.name?index_of("name")!=-1> 122 | 123 | /** 124 | * 根据${par.name}删除${table.table}表数据 125 | */ 126 | public void clean${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 127 | <#if "Date"==par.typeName> 128 | if (${par.name} == null) { 129 | ${par.name} = new Date(); 130 | } 131 | 132 | <#if "Money"==par.typeName> 133 | if (${par.name} == null) { 134 | ${par.name} = new Money(0); 135 | } 136 | 137 | <#if "String"==par.typeName> 138 | if (StringUtils.isBlank(${par.name})){ 139 | ${par.name} = "test_${par.name}"; 140 | } 141 | 142 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 143 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 144 | ${table.tableName?uncap_first}DAO.deleteByExample(exam); 145 | } 146 | 147 | <#if par.name?index_of("Number")!=-1> 148 | 149 | /** 150 | * 根据${par.name}删除${table.table}表数据 151 | */ 152 | public void clean${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 153 | <#if "Date"==par.typeName> 154 | if (${par.name} == null) { 155 | ${par.name} = new Date(); 156 | } 157 | 158 | <#if "Money"==par.typeName> 159 | if (${par.name} == null) { 160 | ${par.name} = new Money(0); 161 | } 162 | 163 | <#if "String"==par.typeName> 164 | if (StringUtils.isBlank(${par.name})){ 165 | ${par.name} = "test_${par.name}"; 166 | } 167 | 168 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 169 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 170 | ${table.tableName?uncap_first}DAO.deleteByExample(exam); 171 | } 172 | 173 | 174 | 175 | <#list table.pars as par> 176 | <#if par.name?index_of("versionId")!=-1> 177 | <#continue> 178 | 179 | <#if par.name?index_of("Id")!=-1 || par.name?index_of("id")!=-1> 180 | 181 | /** 182 | * 根据${par.name}查询${table.table}表数据 183 | */ 184 | public List<${table.tableName}DO> find${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 185 | <#if "Date"==par.typeName> 186 | if (${par.name} == null) { 187 | ${par.name} = new Date(); 188 | } 189 | 190 | <#if "Money"==par.typeName> 191 | if (${par.name} == null) { 192 | ${par.name} = new Money(0); 193 | } 194 | 195 | <#if "String"==par.typeName> 196 | if (StringUtils.isBlank(${par.name})){ 197 | ${par.name} = "test_${par.name}"; 198 | } 199 | 200 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 201 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 202 | return ${table.tableName?uncap_first}DAO.selectByExample(exam); 203 | } 204 | 205 | <#if par.name?index_of("No")!=-1 || par.name?index_of("loginAccount")!=-1> 206 | 207 | /** 208 | * 根据${par.name}查询${table.table}表数据 209 | */ 210 | public List<${table.tableName}DO> find${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 211 | <#if "Date"==par.typeName> 212 | if (${par.name} == null) { 213 | ${par.name} = new Date(); 214 | } 215 | 216 | <#if "Money"==par.typeName> 217 | if (${par.name} == null) { 218 | ${par.name} = new Money(0); 219 | } 220 | 221 | <#if "String"==par.typeName> 222 | if (StringUtils.isBlank(${par.name})){ 223 | ${par.name} = "test_${par.name}"; 224 | } 225 | 226 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 227 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 228 | return ${table.tableName?uncap_first}DAO.selectByExample(exam); 229 | } 230 | 231 | <#if par.name?index_of("Name")!=-1 || par.name?index_of("name")!=-1> 232 | 233 | /** 234 | * 根据${par.name}查询${table.table}表数据 235 | */ 236 | public List<${table.tableName}DO> find${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 237 | <#if "Date"==par.typeName> 238 | if (${par.name} == null) { 239 | ${par.name} = new Date(); 240 | } 241 | 242 | <#if "Money"==par.typeName> 243 | if (${par.name} == null) { 244 | ${par.name} = new Money(0); 245 | } 246 | 247 | <#if "String"==par.typeName> 248 | if (StringUtils.isBlank(${par.name})){ 249 | ${par.name} = "test_${par.name}"; 250 | } 251 | 252 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 253 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 254 | return ${table.tableName?uncap_first}DAO.selectByExample(exam); 255 | } 256 | 257 | <#if par.name?index_of("Number")!=-1> 258 | 259 | /** 260 | * 根据${par.name}查询${table.table}表数据 261 | */ 262 | public List<${table.tableName}DO> find${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name}) { 263 | <#if "Date"==par.typeName> 264 | if (${par.name} == null) { 265 | ${par.name} = new Date(); 266 | } 267 | 268 | <#if "Money"==par.typeName> 269 | if (${par.name} == null) { 270 | ${par.name} = new Money(0); 271 | } 272 | 273 | <#if "String"==par.typeName> 274 | if (StringUtils.isBlank(${par.name})){ 275 | ${par.name} = "test_${par.name}"; 276 | } 277 | 278 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 279 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 280 | return ${table.tableName?uncap_first}DAO.selectByExample(exam); 281 | } 282 | 283 | 284 | <#list table.pars as par> 285 | <#if par.name?index_of("versionId")!=-1> 286 | <#continue> 287 | 288 | <#if par.name?index_of("Id")!=-1 || par.name?index_of("id")!=-1> 289 | 290 | /** 291 | * 根据${par.name}更新${table.table}表数据 292 | */ 293 | public void update${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name},${table.tableName}DO ${table.tableName?uncap_first}DO) { 294 | <#if "Date"==par.typeName> 295 | if (${par.name} == null) { 296 | ${par.name} = new Date(); 297 | } 298 | 299 | <#if "Money"==par.typeName> 300 | if (${par.name} == null) { 301 | ${par.name} = new Money(0); 302 | } 303 | 304 | <#if "String"==par.typeName> 305 | if (StringUtils.isBlank(${par.name})){ 306 | ${par.name} = "test_${par.name}"; 307 | } 308 | 309 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 310 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 311 | ${table.tableName?uncap_first}DAO.updateByExampleSelective(${table.tableName?uncap_first}DO, exam); 312 | } 313 | 314 | <#if par.name?index_of("No")!=-1 || par.name?index_of("loginAccount")!=-1> 315 | 316 | /** 317 | * 根据${par.name}更新${table.table}表数据 318 | */ 319 | public void update${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name},${table.tableName}DO ${table.tableName?uncap_first}DO) { 320 | <#if "Date"==par.typeName> 321 | if (${par.name} == null) { 322 | ${par.name} = new Date(); 323 | } 324 | 325 | <#if "Money"==par.typeName> 326 | if (${par.name} == null) { 327 | ${par.name} = new Money(0); 328 | } 329 | 330 | <#if "String"==par.typeName> 331 | if (StringUtils.isBlank(${par.name})){ 332 | ${par.name} = "test_${par.name}"; 333 | } 334 | 335 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 336 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 337 | ${table.tableName?uncap_first}DAO.updateByExampleSelective(${table.tableName?uncap_first}DO, exam); 338 | } 339 | 340 | <#if par.name?index_of("Name")!=-1 || par.name?index_of("name")!=-1> 341 | 342 | /** 343 | * 根据${par.name}更新${table.table}表数据 344 | */ 345 | public void update${table.tableName}By${par.name?cap_first}(${par.typeName} ${par.name},${table.tableName}DO ${table.tableName?uncap_first}DO) { 346 | <#if "Date"==par.typeName> 347 | if (${par.name} == null) { 348 | ${par.name} = new Date(); 349 | } 350 | 351 | <#if "Money"==par.typeName> 352 | if (${par.name} == null) { 353 | ${par.name} = new Money(0); 354 | } 355 | 356 | <#if "String"==par.typeName> 357 | if (StringUtils.isBlank(${par.name})){ 358 | ${par.name} = "test_${par.name}"; 359 | } 360 | 361 | ${table.tableName}DOExample exam = new ${table.tableName}DOExample(); 362 | exam.createCriteria().and${par.name?cap_first}EqualTo(${par.name}); 363 | ${table.tableName?uncap_first}DAO.updateByExampleSelective(${table.tableName?uncap_first}DO, exam); 364 | } 365 | 366 | 367 | 368 | 369 | } 370 | -------------------------------------------------------------------------------- /src/main/resources/lib/mysql-connector-java-5.1.30.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ychaoyang/autotest/858e5cc8dd0a27585ff494e0d79303d3f4c0b9ca/src/main/resources/lib/mysql-connector-java-5.1.30.jar -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 11 | 12 | 13 | 14 | 15 | 16 | 17 | ${LOG_HOME}/autotest-%d{yyyy-MM-dd}.log 18 | 19 | 30 20 | 21 | 22 | 23 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 24 | 25 | 26 | 27 | 5MB 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/resources/webdriver/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ychaoyang/autotest/858e5cc8dd0a27585ff494e0d79303d3f4c0b9ca/src/main/resources/webdriver/chromedriver.exe -------------------------------------------------------------------------------- /src/test/java/com/autotest/Generator.java: -------------------------------------------------------------------------------- 1 | package com.autotest; 2 | 3 | import com.autotest.generate.GenerateFacadeCase; 4 | import com.autotest.example.QueryUserFacade; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.extension.ExtendWith; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit.jupiter.SpringExtension; 9 | 10 | public class Generator { 11 | 12 | @Test 13 | public void genFacadeCase() { 14 | String author = "huairen"; 15 | String methodName = "queryUserById"; 16 | String packag = "test"; 17 | new GenerateFacadeCase().generate(QueryUserFacade.class, methodName, packag, author, Generator.class); 18 | } 19 | 20 | 21 | } -------------------------------------------------------------------------------- /src/test/java/com/autotest/example/QueryOrder.java: -------------------------------------------------------------------------------- 1 | package com.autotest.example; 2 | 3 | /** 4 | * @author huairen 5 | * Created on 18/6/2. 6 | */ 7 | public class QueryOrder { 8 | 9 | private int id; 10 | 11 | private String name; 12 | 13 | public int getId() { 14 | return id; 15 | } 16 | 17 | public void setId(int id) { 18 | this.id = id; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | public void setName(String name) { 26 | this.name = name; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "QueryOrder{" + 32 | "id=" + id + 33 | ", name='" + name + '\'' + 34 | '}'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/example/QueryUserFacade.java: -------------------------------------------------------------------------------- 1 | package com.autotest.example; 2 | 3 | 4 | /** 5 | * @author huairen 6 | * Created on 18/6/2. 7 | */ 8 | public interface QueryUserFacade { 9 | 10 | UserResult queryUserById(QueryOrder order); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/example/UserResult.java: -------------------------------------------------------------------------------- 1 | package com.autotest.example; 2 | 3 | /** 4 | * @author huairen 5 | * Created on 18/6/2. 6 | */ 7 | public class UserResult { 8 | 9 | private String code; 10 | 11 | private Long id; 12 | 13 | private String name; 14 | 15 | private Integer age; 16 | 17 | public String getCode() { 18 | return code; 19 | } 20 | 21 | public void setCode(String code) { 22 | this.code = code; 23 | } 24 | 25 | public Long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Long id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public Integer getAge() { 42 | return age; 43 | } 44 | 45 | public void setAge(Integer age) { 46 | this.age = age; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | StringBuilder sb = new StringBuilder(); 52 | sb.append(getClass().getSimpleName()); 53 | sb.append(" ["); 54 | sb.append(", id=").append(id); 55 | sb.append(", name=").append(name); 56 | sb.append(", age=").append(age); 57 | sb.append("]"); 58 | return sb.toString(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/test/HttpTest.java: -------------------------------------------------------------------------------- 1 | package com.autotest.test; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.autotest.annotation.AutoTest; 5 | import com.autotest.base.AutoTestBase; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.util.LinkedMultiValueMap; 8 | import org.springframework.util.MultiValueMap; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | /** 12 | * Created by yu on 17/12/26. 13 | */ 14 | public class HttpTest extends AutoTestBase { 15 | 16 | protected RestTemplate restTemplate = new RestTemplate(); 17 | 18 | /** 19 | * 有道翻译接口 20 | */ 21 | @AutoTest(file = "httpTest.csv") 22 | void httpTest(int testId) { 23 | String url = "http://fanyi.youdao.com/translate"; 24 | MultiValueMap map = new LinkedMultiValueMap(); 25 | //需要翻译的单词 26 | String word = "today"; 27 | map.add("i", word); 28 | map.add("type", "auto"); 29 | map.add("doctype", "json"); 30 | map.add("xmlVersion", "1.8"); 31 | // 调用接口 32 | ResponseEntity response = restTemplate.postForEntity(url, map, String.class); 33 | print("原单词:" + word); 34 | print("翻译后:" + JSON.parseObject(response.getBody()).getJSONArray("translateResult").getJSONArray(0).get(0)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/test/MybatisTest.java: -------------------------------------------------------------------------------- 1 | package com.autotest.test; 2 | 3 | import com.autotest.annotation.AutoTest; 4 | import com.autotest.base.SpringBootTestBase; 5 | import com.autotest.testbase.SchoolTestBase; 6 | import dal.model.school.StudentDO; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | public class MybatisTest extends SpringBootTestBase { 10 | 11 | @Autowired 12 | SchoolTestBase schoolTestBase; 13 | 14 | @AutoTest(file = "mybatisTest.csv") 15 | void mybatisTest( 16 | int testId, 17 | StudentDO studentDO 18 | ) { 19 | //插入数据 20 | schoolTestBase.insertStudent(studentDO); 21 | //查询数据 22 | print(schoolTestBase.findStudentByName(studentDO.getName())); 23 | //清除数据 24 | schoolTestBase.cleanStudentByName(studentDO.getName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/test/QueryUserFacadeQueryUserByIdTest.java: -------------------------------------------------------------------------------- 1 | package com.autotest.test; 2 | 3 | import com.autotest.base.SpringBootTestBase; 4 | import com.autotest.annotation.AutoTest; 5 | import org.junit.jupiter.api.DisplayName; 6 | import com.alibaba.dubbo.config.annotation.Reference; 7 | import java.util.Date; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import com.autotest.example.UserResult; 11 | import com.autotest.example.QueryUserFacade; 12 | import com.autotest.example.QueryOrder; 13 | 14 | 15 | 16 | /** 17 | * @author huairen 18 | * Created on 2018年06月02日. 19 | */ 20 | public class QueryUserFacadeQueryUserByIdTest extends SpringBootTestBase{ 21 | 22 | @Reference(version = "1.0") 23 | QueryUserFacade queryUserFacade; 24 | 25 | @AutoTest(file = "test/queryUserFacadeQueryUserByIdTestSuccess.csv") 26 | public void queryUserFacadeQueryUserByIdTestSuccess( 27 | // 基本参数 28 | int testId, 29 | // 业务参数 30 | QueryOrder order 31 | ) { 32 | // 清除数据 33 | // 准备数据 34 | // 测试过程 35 | // 调用接口 36 | UserResult result = queryUserFacade.queryUserById(order); 37 | // 结果验证 38 | // 数据验证 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/test/WebTest.java: -------------------------------------------------------------------------------- 1 | package com.autotest.test; 2 | 3 | import com.autotest.testbase.web.WebTestBase; 4 | import org.junit.jupiter.api.DisplayName; 5 | import org.junit.jupiter.api.Test; 6 | import org.openqa.selenium.By; 7 | 8 | import static com.codeborne.selenide.Selenide.$; 9 | import static com.codeborne.selenide.Selenide.open; 10 | import static com.codeborne.selenide.Selenide.title; 11 | 12 | /** 13 | * Created by huairen on 2017/8/7. 14 | */ 15 | public class WebTest extends WebTestBase { 16 | 17 | @Test 18 | @DisplayName("测试百度搜索页面") 19 | void baiduTest() { 20 | open("http://www.baidu.com"); 21 | $(By.id("kw")).setValue("junit"); 22 | $(By.id("su")).click(); 23 | print(title()); 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/testbase/SchoolTestBase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.testbase; 2 | 3 | import java.util.List; 4 | import java.util.Date; 5 | import org.junit.platform.commons.util.StringUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | import java.math.BigDecimal; 9 | import dal.dao.school.*; 10 | import dal.model.school.*; 11 | 12 | /** 13 | * @author autotest 14 | * Created on 2018/06/02. 15 | */ 16 | @Service 17 | public class SchoolTestBase { 18 | 19 | @Autowired 20 | StudentDAO studentDAO; 21 | 22 | /** 23 | * 插入student表数据 24 | */ 25 | public void insertStudent(StudentDO studentDO) { 26 | studentDAO.insert(studentDO); 27 | } 28 | 29 | /** 30 | * 插入student表数据 31 | */ 32 | public void insertStudent( 33 | long id, 34 | String name, 35 | Integer age 36 | ) { 37 | StudentDO studentDO = new StudentDO(); 38 | studentDO.setId(id); 39 | studentDO.setName(name); 40 | studentDO.setAge(age); 41 | studentDAO.insert(studentDO); 42 | } 43 | 44 | 45 | /** 46 | * 根据id删除student表数据 47 | */ 48 | public void cleanStudentById(long id) { 49 | StudentDOExample exam = new StudentDOExample(); 50 | exam.createCriteria().andIdEqualTo(id); 51 | studentDAO.deleteByExample(exam); 52 | } 53 | 54 | /** 55 | * 根据name删除student表数据 56 | */ 57 | public void cleanStudentByName(String name) { 58 | if (StringUtils.isBlank(name)){ 59 | name = "test_name"; 60 | } 61 | StudentDOExample exam = new StudentDOExample(); 62 | exam.createCriteria().andNameEqualTo(name); 63 | studentDAO.deleteByExample(exam); 64 | } 65 | 66 | 67 | /** 68 | * 根据id查询student表数据 69 | */ 70 | public List findStudentById(long id) { 71 | StudentDOExample exam = new StudentDOExample(); 72 | exam.createCriteria().andIdEqualTo(id); 73 | return studentDAO.selectByExample(exam); 74 | } 75 | 76 | /** 77 | * 根据name查询student表数据 78 | */ 79 | public List findStudentByName(String name) { 80 | if (StringUtils.isBlank(name)){ 81 | name = "test_name"; 82 | } 83 | StudentDOExample exam = new StudentDOExample(); 84 | exam.createCriteria().andNameEqualTo(name); 85 | return studentDAO.selectByExample(exam); 86 | } 87 | 88 | /** 89 | * 根据id更新student表数据 90 | */ 91 | public void updateStudentById(long id,StudentDO studentDO) { 92 | StudentDOExample exam = new StudentDOExample(); 93 | exam.createCriteria().andIdEqualTo(id); 94 | studentDAO.updateByExampleSelective(studentDO, exam); 95 | } 96 | 97 | /** 98 | * 根据name更新student表数据 99 | */ 100 | public void updateStudentByName(String name,StudentDO studentDO) { 101 | if (StringUtils.isBlank(name)){ 102 | name = "test_name"; 103 | } 104 | StudentDOExample exam = new StudentDOExample(); 105 | exam.createCriteria().andNameEqualTo(name); 106 | studentDAO.updateByExampleSelective(studentDO, exam); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/test/java/com/autotest/testbase/web/WebTestBase.java: -------------------------------------------------------------------------------- 1 | package com.autotest.testbase.web; 2 | 3 | import com.autotest.base.SpringBootTestBase; 4 | import com.codeborne.selenide.Configuration; 5 | import org.junit.jupiter.api.AfterEach; 6 | import org.junit.jupiter.api.BeforeAll; 7 | 8 | import static com.codeborne.selenide.Selenide.close; 9 | 10 | public class WebTestBase extends SpringBootTestBase { 11 | 12 | @BeforeAll 13 | static void init() { 14 | System.setProperty("webdriver.chrome.driver", Thread.currentThread().getContextClassLoader() 15 | .getResource("webdriver/" + "chromedriver.exe").getPath()); 16 | System.setProperty("chromeoptions.args", "disable-infobars"); 17 | Configuration.browser = "chrome"; 18 | Configuration.browserSize = "1920x1080"; 19 | Configuration.timeout = 6000; 20 | Configuration.screenshots = false; 21 | } 22 | 23 | @AfterEach 24 | void tearDown() { 25 | close(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/resources/autotest/csvTest.csv: -------------------------------------------------------------------------------- 1 | testId,memo,result 2 | 1001, 第一条测试用例 , SUCCESS 3 | 1002, 第二条测试用例 , FAIL -------------------------------------------------------------------------------- /src/test/resources/autotest/httpTest.csv: -------------------------------------------------------------------------------- 1 | result,testId 2 | SUCCESS,1001 3 | -------------------------------------------------------------------------------- /src/test/resources/autotest/mybatisTest.csv: -------------------------------------------------------------------------------- 1 | testId,id,name,age 2 | 1001,1,~小明,18 3 | 1001,2,~小红,20 -------------------------------------------------------------------------------- /src/test/resources/autotest/test/queryUserFacadeQueryUserByIdTestSuccess.csv: -------------------------------------------------------------------------------- 1 | testId,id,name 2 | 1001,20181206,xiaoming -------------------------------------------------------------------------------- /student.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `student` ( 2 | `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'id', 3 | `name` VARCHAR(40) NOT NULL DEFAULT '' COMMENT '名称', 4 | `age` INT(6) NOT NULL DEFAULT '0' COMMENT '年龄', 5 | PRIMARY KEY (`id`) 6 | )DEFAULT CHARSET=utf8 COMMENT='学生表' 7 | --------------------------------------------------------------------------------