Skip to content

Commit

Permalink
fix(#1049): Starting JBang script support
Browse files Browse the repository at this point in the history
- Introduce TestSource model that holds polyglot test sources (.xml, .yaml, .groovy, .feature)
- Enhance TestNG TestEngine implementation to support running polyglot Citrus tests (xml, yaml, groovy)
- Enhance Cucumber TestEngine to properly handle feature files passed to the run command
- Introduce citrus-jbang module in tools
- Add JBang catalog pointing to Citrus JBang CLI script
- Add CitrusJBangMain script with following commands
- Init command to create test template (.yaml, .xml, .groovy, .feature)
- ListTests command list all running tests
- Run command able to run tests via TestEngine API
- Fix java util logging to send all log events to SLF4J
  • Loading branch information
christophd committed Nov 9, 2023
1 parent 1aabea7 commit 2a87abe
Show file tree
Hide file tree
Showing 43 changed files with 1,809 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.LogManager;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -65,7 +66,19 @@ private CitrusSettings() {
if (logger.isTraceEnabled()) {
logger.trace("Unable to locate Citrus application properties", e);
} else {
logger.info("Unable to locate Citrus application properties");
logger.debug("Unable to locate Citrus application properties");
}
}

try (InputStream is = CitrusSettings.class.getClassLoader().getResourceAsStream("logging.properties")) {
if (is != null) {
LogManager.getLogManager().readConfiguration(is);
}
} catch (Exception e) {
if (logger.isTraceEnabled()) {
logger.trace("Unable to configure Java util logging", e);
} else {
logger.info("Unable to configure Java util logging");
}
}
}
Expand Down
77 changes: 25 additions & 52 deletions core/citrus-api/src/main/java/org/citrusframework/TestClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,23 @@

package org.citrusframework;

import org.citrusframework.exceptions.CitrusRuntimeException;

/**
* @author Christoph Deppisch
* @since 2.7
*/
public class TestClass {

/** Test name and optional method */
private String name;
private String method;
public class TestClass extends TestSource {

public TestClass() {
super();
}
/** Optional test method */
private final String method;

public TestClass(String name) {
this.name = name;
public TestClass(Class<?> type) {
this(type, null);
}

public TestClass(String name, String method) {
this(name);
public TestClass(Class<?> type, String method) {
super(type);
this.method = method;
}

Expand All @@ -48,33 +45,6 @@ public String getMethod() {
return method;
}

/**
* Sets the method.
*
* @param method
*/
public void setMethod(String method) {
this.method = method;
}

/**
* Gets the name.
*
* @return
*/
public String getName() {
return name;
}

/**
* Sets the name.
*
* @param name
*/
public void setName(String name) {
this.name = name;
}

/**
* Read String representation and construct proper test class instance. Read optional method name information and class name using format
* "fully.qualified.class.Name#optionalMethodName()"
Expand All @@ -83,20 +53,23 @@ public void setName(String name) {
* @return
*/
public static TestClass fromString(String testClass) {
String className;
String methodName = null;
if (testClass.contains("#")) {
className = testClass.substring(0, testClass.indexOf("#"));
methodName = testClass.substring(testClass.indexOf("#") + 1);
} else {
className = testClass;
}
try {
String className;
String methodName = null;
if (testClass.contains("#")) {
className = testClass.substring(0, testClass.indexOf("#"));
methodName = testClass.substring(testClass.indexOf("#") + 1);
} else {
className = testClass;
}

TestClass test = new TestClass(className);
if (methodName != null && !methodName.isBlank()) {
test.setMethod(methodName);
}
if (methodName != null && !methodName.isBlank()) {
return new TestClass(Class.forName(className), methodName);
}

return test;
return new TestClass(Class.forName(className));
} catch (ClassNotFoundException e) {
throw new CitrusRuntimeException("Failed to create test class", e);
}
}
}
67 changes: 67 additions & 0 deletions core/citrus-api/src/main/java/org/citrusframework/TestSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2006-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.citrusframework;

/**
* @author Christoph Deppisch
* @since 4.0
*/
public class TestSource {

/** Test type, name and optional sourceFile */
private final String type;
private final String name;
private final String filePath;

public TestSource(String type, String name) {
this(type, name, null);
}

public TestSource(String type, String name, String filePath) {
this.type = type;
this.name = name;
this.filePath = filePath;
}

public TestSource(Class<?> testClass) {
this("java", testClass.getName());
}

/**
* The test source type. Usually one of java, xml, groovy, yaml.
* @return
*/
public String getType() {
return type;
}

/**
* Gets the name.
* @return
*/
public String getName() {
return name;
}

/**
* Optional source file path.
* @return
*/
public String getFilePath() {
return filePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@
import java.util.List;
import java.util.Map;

import org.citrusframework.TestClass;
import org.citrusframework.TestSource;

/**
* @author Christoph Deppisch
* @since 2.7.4
*/
public class TestRunConfiguration {

/** Test to execute at runtime */
/** Test engine */
private String engine = "junit4";

/** Test to execute at runtime */
private List<TestClass> testClasses = new ArrayList<>();
private final List<TestSource> sources = new ArrayList<>();

/** Package to execute at runtime */
private List<String> packages = new ArrayList<>();
private final List<String> packages = new ArrayList<>();

/** Include tests based on these test name pattern */
private String[] includes = new String[] { "^.*IT$", "^.*ITCase$", "^IT.*$" };
Expand Down Expand Up @@ -68,21 +68,21 @@ public void setEngine(String engine) {
}

/**
* Gets the testClasses.
* Gets the sources.
*
* @return
*/
public List<TestClass> getTestClasses() {
return testClasses;
public List<TestSource> getTestSources() {
return sources;
}

/**
* Sets the testClasses.
* Sets the sources.
*
* @param testClasses
* @param sources
*/
public void setTestClasses(List<TestClass> testClasses) {
this.testClasses = testClasses;
public void setTestSources(List<TestSource> sources) {
this.sources.addAll(sources);
}

/**
Expand All @@ -100,7 +100,7 @@ public List<String> getPackages() {
* @param packages
*/
public void setPackages(List<String> packages) {
this.packages = packages;
this.packages.addAll(packages);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public List<TestClass> findTestsInPackage(String packageName) {

return classes.stream()
.distinct()
.map(TestClass::new)
.map(TestClass::fromString)
.collect(Collectors.toList());
} catch (IOException e) {
throw new CitrusRuntimeException(String.format("Failed to scan classpath package '%s'", packageName), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public List<TestClass> findTestsInPackage(String packageToScan) {
String className = FileUtils.getBaseName(entry.getName()).replace( "/", "." );
if (packageToScan.replace( ".", "/" ).startsWith(entry.getName()) && isIncluded(className)) {
logger.info("Found test class candidate in test jar file: " + entry.getName());
testClasses.add(new TestClass(className));
testClasses.add(TestClass.fromString(className));
}
}
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.Stack;

import org.citrusframework.CitrusSettings;
import org.citrusframework.TestSource;
import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.spi.Resource;
Expand Down Expand Up @@ -427,4 +428,17 @@ public static byte[] copyToByteArray(InputStream inputStream) {
public static String constructContentType(String contentType, Charset charset) {
return contentType + FILE_PATH_CHARSET_PARAMETER + charset;
}

/**
* Read String representation and construct proper test source instance.
* Extract source type from give file extension and try to set proper test source name from given file name.
*
* @param sourceFile
* @return
*/
public static TestSource getTestSource(String sourceFile) {
String ext = getFileExtension(sourceFile);
String name = getFileName(sourceFile);
return new TestSource(ext, name, sourceFile);
}
}
9 changes: 9 additions & 0 deletions jbang-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"catalogs": {},
"aliases": {
"citrus": {
"script-ref": "tools/jbang/dist/CitrusJBang.java",
"description": "Run Citrus tests"
}
}
}
Loading

0 comments on commit 2a87abe

Please sign in to comment.