自动化测试,首先想到的就是fitnesse。但是毕竟fitnesse功能优先,在自动化测试中,会遇到瓶颈。这个时候就需要对fitnesse进行二次开发。fitnesse不但有可以直接部署运行的jar包,在github上也可以下载到源代码。
源码是用gradle工具进行构建的。
Github下载地址:https://github.com/unclebob/fitnesse.git
一、Gradle安装
我使用的是IDEA 2017,对应的gradle版本是3.5,安装过程很简单,网上一查便知。完成后需要配置系统环境变量:GRADLE_HOME、GRADLE_USER_HOME
以及path
变量。
Path变量
打开cmd命令行,然后运行gradle -v
,会显示gradle的信息,则表示安装成功。
二、IDEA导入fitnesse项目
打开idea,导入项目后,需要配置很多信息。gradle目录下的gradle-wrapper.properties中改成版本3.5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-3.5-bin.zip
zipStorePath=wrapper/dists
build.gradle文件是利用gradle进行项目构建的核心配置文件,以下是经过我修改后可行的配置。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.1.9'
}
}
plugins {
id 'java'
id "maven-publish"
id "com.jfrog.bintray" version "1.8.4"
id "com.github.ben-manes.versions" version "0.20.0"
}
apply plugin: "info.solidsoft.pitest"
version = new Date().format('yyyyMMdd')
println "Building FitNesse v${project.version}..."
repositories {
mavenCentral()
}
configurations {
lesscss
optional
compile {
transitive = false
extendsFrom optional
}
runtime {
transitive = false
}
}
sourceSets {
main {
java.srcDir 'src'
resources.srcDir 'src'
output.resourcesDir output.classesDir
}
test {
java.srcDir 'test'
}
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
dependencies {
compile "org.htmlparser:htmlparser:2.1"
compile "org.htmlparser:htmllexer:2.1"
compile ("org.apache.velocity:velocity-engine-core:2.0") {
exclude group:"org.apache.commons", module: "commons-lang3"
exclude group: 'org.slf4j', module: 'slf4j-api'
}
compile "org.apache.commons:commons-lang3:3.8.1"
compile "org.slf4j:slf4j-api:1.7.25"
compile "org.slf4j:slf4j-jdk14:1.7.25"
compile "org.json:json:20180813"
compile "com.googlecode.java-diff-utils:diffutils:1.3.0"
optional "org.apache.ant:ant:1.10.5"
optional "junit:junit:4.12"
testCompile "junit:junit:4.12"
testCompile "org.mockito:mockito-core:2.23.4"
testCompile "org.hamcrest:hamcrest-all:1.3"
testCompile "net.javacrumbs.json-unit:json-unit:2.2.0"
compileOnly files('lib/joda-time-2.3.jar')
lesscss "org.mozilla:rhino:1.7.10"
}
task fitNesseVersion {
def versionFile = new File("${sourceSets.main.output.resourcesDir}/META-INF/FitNesseVersion.txt")
versionFile.parentFile.mkdirs()
versionFile.text="v${version}"
}
task compileBootstrap(type: LessCompiler) {
inputDir file('src/fitnesse/resources/bootstrap/less')
mainLessFile = 'fitnesse-bootstrap.less'
cssFile file("${sourceSets.main.output.resourcesDir}/fitnesse/resources/bootstrap/css/fitnesse-bootstrap.css")
classpath configurations.lesscss
}
task createUpdateLists(type: WikiFileListBuilderTask) {
outputDirectory = "${sourceSets.main.output.resourcesDir}/Resources"
files = {
// Make sure only files in version control are added to the default wiki contents
"git ls-files FitNesseRoot".execute().text.readLines()
}
doNotReplaceFiles = [
"FitNesseRoot/content.txt",
"FitNesseRoot/properties.xml",
"FitNesseRoot/FrontPage/content.txt",
"FitNesseRoot/FrontPage/properties.xml",
"FitNesseRoot/PageHeader/content.txt",
"FitNesseRoot/PageHeader/properties.xml",
"FitNesseRoot/PlugIns/content.txt",
"FitNesseRoot/PlugIns/properties.xml",
"FitNesseRoot/PageFooter/content.txt",
"FitNesseRoot/PageFooter/properties.xml",
"FitNesseRoot/TemplateLibrary/content.txt",
"FitNesseRoot/TemplateLibrary/properties.xml",
"FitNesseRoot/TemplateLibrary/StaticPage/content.txt",
"FitNesseRoot/TemplateLibrary/StaticPage/properties.xml",
"FitNesseRoot/TemplateLibrary/SuitePage/content.txt",
"FitNesseRoot/TemplateLibrary/SuitePage/properties.xml",
"FitNesseRoot/TemplateLibrary/TestPage/content.txt",
"FitNesseRoot/TemplateLibrary/TestPage/properties.xml" ]
}
processResources.dependsOn "fitNesseVersion", "compileBootstrap", "createUpdateLists"
task copyRuntimeLibs(type: Copy) {
into "lib"
from configurations.runtime
}
test {
dependsOn copyRuntimeLibs
maxParallelForks 1
}
pitest {
targetClasses = ['fit.*', 'fitnesse.*']
pitestVersion = "1.4.3"
threads = 1 // We can not deal with parallel execution yet
outputFormats = ['XML', 'HTML']
}
task run(type: JavaExec) {
dependsOn classes, copyRuntimeLibs
classpath = sourceSets.main.runtimeClasspath
main "fitnesseMain.FitNesseMain"
args "-p", "8001", "-e", "0"
}
jar {
dependsOn createUpdateLists
from {
//添加依懒到打包文件
configurations.runtime.collect{zipTree(it)}
}
into('Resources') {
from('.') {
include createUpdateLists.wikiFiles as String[]
}
}
duplicatesStrategy = 'exclude'
manifest {
attributes("Main-Class": "fitnesseMain.FitNesseMain",
"Implementation-Version": version)
}
}
task standaloneJar(type: Jar) {
baseName = 'fitnesse'
classifier = 'standalone'
from {
(configurations.compile - configurations.optional).collect { zipTree(it) }
} {
exclude 'META-INF/**'
}
from jar.outputs.files.collect {
zipTree(it)
}
manifest {
attributes("Main-Class": "fitnesseMain.FitNesseMain",
"Implementation-Version": version)
}
}
task slimJar(type: Jar) {
baseName = 'fitnesse'
classifier = 'slim'
from { jar.outputs.files.collect { zipTree(it) } }
{
include 'fitnesse/html/*.class'
include 'fitnesse/slim/**/*.class'
include 'fitnesse/socketservice/*.class'
include 'util/*.class'
include 'fitnesse/util/StringUtils.class'
}
manifest {
attributes("Implementation-Version": version)
}
}
task acceptanceTest(type: JavaExec) {
mustRunAfter test
onlyIf { test.didWork }
classpath = standaloneJar.outputs.files
main "fitnesseMain.FitNesseMain"
args "-o", "-c", "FitNesse.SuiteAcceptanceTests?suite&format=text"
}
check.dependsOn acceptanceTest
task javadocJar(type: Jar) {
mustRunAfter check
classifier = 'javadoc'
from javadoc
}
task sourcesJar(type: Jar) {
mustRunAfter check
classifier = 'sources'
from sourceSets.main.allSource
}
task releaseTag(type: Exec) {
commandLine 'git', 'tag', project.version
doLast {
println "Tagged release ${project.version}"
}
}
task publishTag(type: Exec) {
commandLine 'git', 'push', '--tags'
shouldRunAfter releaseTag
}
task prepareSnapshotRepo {
bintray.pkg.repo = 'edge'
}
task prepareReleaseRepo {
bintray.pkg.repo = 'release'
}
bintrayUpload.mustRunAfter prepareSnapshotRepo, prepareReleaseRepo
task snapshotRelease {
dependsOn prepareSnapshotRepo, bintrayUpload
}
task release {
dependsOn releaseTag, prepareReleaseRepo, bintrayUpload, publishTag
}
clean {
delete "lib"
}
publishing {
publications {
FitNesseRelease(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
artifact standaloneJar
artifact slimJar
groupId 'org.fitnesse'
artifactId 'fitnesse'
pom.withXml {
asNode().get('version') + {
resolveStrategy = Closure.DELEGATE_FIRST
name('FitNesse')
description('The fully integrated standalone wiki, and acceptance testing framework.')
url('http://fitnesse.org')
packaging('jar')
}
asNode().append(pomLicenses())
asNode().append(pomScm())
asNode().append(pomDevelopers())
// Clean up scope entries added by the pom generator:
asNode().dependencies.'*'.findAll() {
if (project.configurations.optional.allDependencies
.find { dep -> dep.name == it.artifactId.text()}) {
def xmlOptional = it.optional[0]
if ( !xmlOptional ) {
xmlOptional = it.appendNode('optional')
}
xmlOptional.value = 'true'
}
}
}
}
}
}
bintray {
user = System.getenv("BINTRAY_USER") ?: 'Define your Bintray user name in BINTRAY_USER'
key = System.getenv("BINTRAY_API_KEY") ?: 'Define your Bintray BINTRAY_API_KEY'
publications = ['FitNesseRelease']
publish = true
pkg {
name = 'fitnesse'
userOrg = 'fitnesse'
licenses = ['CPL-1.0']
websiteUrl = 'http://fitnesse.org'
vcsUrl = 'https://github.com/unclebob/fitnesse.git'
publicDownloadNumbers = true
githubRepo = 'unclebob/fitnesse'
version {
name = project.version
desc = "FitNesse release ${project.version}"
vcsTag = project.version
gpg {
sign = true
}
}
}
}
wrapper {
gradleVersion = '5.3.1'
}
def pomLicenses() {
new NodeBuilder().licenses {
license {
name 'Common Public License version 1.0'
url 'http://www.opensource.org/licenses/cpl1.0'
distribution 'repo'
}
}
}
def pomScm() {
new NodeBuilder().scm {
connection 'scm:git:git://github.com/unclebob/fitnesse.git'
developerConnection 'scm:git:git@github.com:unclebob/fitnesse.git'
url 'scm:git:http://github.com/unclebob/fitnesse'
}
}
def pomDevelopers() {
new NodeBuilder().developers {
developer {
id 'unclebob'
name 'Robert C. Martin'
email 'unclebob@cleancoder.com'
}
}
}
修改完成后,refresh一下gradle项目,会根据build.gradle文件的配置,对项目进行以下更新。
现在运行一下,可能会发现有空指针的现象,定位后发现,缺少Resources文件夹。所以需要导入一下这个资源文件夹。可以直接导入fitnesse-standalone.jar中的Resources文件夹,这样可以解决空指针的问题。另外,src/fitnesse/resources/bootstrap
下没有css样式文件夹,这个也需要从fitnesse-standalone.jar中导入进来。
缺少的css样式
缺少的Resources文件目录
三、运行和构建
踩了一系列的坑之后,终于可以运行了,运行的结果正是我们想要看到的结果。
然后需要打包发布,这里遇到很多问题,可能打包成功后,运行报错。有错误的时候,百度不到也很正常,要善于思考,定会解决。刚开始不是很顺利,运行jar包缺少对应的模块,之后改了一下build.gradle的配置
,添加了下面一段话,就成功了。
打包的时候,需要进入gradle工程的主目录下,也就是build.gradle文件所在的目录下。运行命令:gradle jar
,打包完成后,会在主目录下的build/libs
下生成我们需要的jar文件。
来源:CSDN
作者:inception~
链接:https://blog.csdn.net/qq_18840365/article/details/103654759