fix: Better handle the overload test methods (#1526)
- change the test id of JUnit 5 and TestNG. The new test id of these two frameworks will contain the method parameter types, so that users can specify any one of the overload test methods and see the results. - update the contribution guide. - add some test cases for TestNG.
This commit is contained in:
Родитель
0c14d0b92e
Коммит
d46a5923f9
|
@ -31,7 +31,11 @@
|
|||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["${workspaceFolder}/test/test-projects/junit", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/suite" ],
|
||||
"sourceMaps": true,
|
||||
"outFiles": [ "${workspaceFolder}/dist/**/*.js" ],
|
||||
"pauseForSourceMap": true,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js",
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: compile"
|
||||
},
|
||||
{
|
||||
|
@ -41,7 +45,10 @@
|
|||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["${workspaceFolder}/test/test-projects/simple", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/unmanaged-folder-suite" ],
|
||||
"sourceMaps": true,
|
||||
"outFiles": [ "${workspaceFolder}/dist/**/*.js" ],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js",
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: compile"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -64,3 +64,14 @@ If you want to build your own private build, run `npx @vscode/vsce@latest packag
|
|||
|
||||
### Check Lint Errors:
|
||||
Run `npm run lint` to check lint errors.
|
||||
|
||||
## Running the test suite
|
||||
|
||||
You can run tests using `npm run test` or by using the `Launch Tests` Run and Debug configurations in VS Code.
|
||||
|
||||
### VS Code run and debug configurations
|
||||
|
||||
There are two test suite folders for this project. In VS Code you'll see the following run targets:
|
||||
- `Launch Tests (maven junit)`: This will run the tests in the `./test/suite` folder.
|
||||
- `Launch Tests (unmanaged-folder)`: This will run the tests in the `./test/unmanaged-folder-suite` folder.
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public class JavaTestItemBuilder {
|
|||
} else {
|
||||
displayName = JavaElementLabels.getElementLabel(this.element, JavaElementLabels.ALL_DEFAULT);
|
||||
}
|
||||
final String fullName = TestItemUtils.parseFullName(this.element, this.level);
|
||||
final String fullName = TestItemUtils.parseFullName(this.element, this.level, this.kind);
|
||||
if (uri == null) {
|
||||
uri = JDTUtils.getFileURI(this.element.getResource());
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
package com.microsoft.java.test.plugin.util;
|
||||
|
||||
import com.microsoft.java.test.plugin.model.TestKind;
|
||||
import com.microsoft.java.test.plugin.model.TestLevel;
|
||||
|
||||
import org.eclipse.jdt.core.IJavaElement;
|
||||
import org.eclipse.jdt.core.IMethod;
|
||||
import org.eclipse.jdt.core.ISourceRange;
|
||||
|
@ -21,6 +21,7 @@ import org.eclipse.jdt.core.IType;
|
|||
import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.core.SourceRange;
|
||||
import org.eclipse.jdt.ls.core.internal.JDTUtils;
|
||||
import org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
|
@ -39,14 +40,23 @@ public class TestItemUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static String parseFullName(IJavaElement element, TestLevel level) {
|
||||
public static String parseFullName(IJavaElement element, TestLevel level, TestKind kind) {
|
||||
switch (level) {
|
||||
case CLASS:
|
||||
final IType type = (IType) element;
|
||||
return type.getFullyQualifiedName();
|
||||
case METHOD:
|
||||
final IMethod method = (IMethod) element;
|
||||
return method.getDeclaringType().getFullyQualifiedName() + "#" + method.getElementName();
|
||||
if (kind == TestKind.JUnit5 || kind == TestKind.TestNG) {
|
||||
final String className = method.getDeclaringType().getFullyQualifiedName();
|
||||
// Generics don't come through in the test results, so we need to strip
|
||||
// them out now.
|
||||
final String methodName = JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT)
|
||||
.replaceAll("<.*?>", "");
|
||||
return className + "#" + methodName;
|
||||
} else {
|
||||
return method.getDeclaringType().getFullyQualifiedName() + "#" + method.getElementName();
|
||||
}
|
||||
default:
|
||||
return element.getElementName();
|
||||
}
|
||||
|
|
|
@ -49,16 +49,16 @@ public class TestNGLauncher implements ITestLauncher {
|
|||
return classToMethodsMap;
|
||||
}
|
||||
|
||||
private static String getClassName(String clazz) throws ClassNotFoundException {
|
||||
return Class.forName(clazz, false, TestNGLauncher.class.getClassLoader()).getName();
|
||||
private static String getClassName(String testId) throws ClassNotFoundException {
|
||||
return Class.forName(testId, false, TestNGLauncher.class.getClassLoader()).getName();
|
||||
}
|
||||
|
||||
private static String getClassNameFromMethod(String clazz) throws ClassNotFoundException {
|
||||
return Class.forName(clazz.substring(0, clazz.lastIndexOf("#")), false,
|
||||
private static String getClassNameFromMethod(String testId) throws ClassNotFoundException {
|
||||
return Class.forName(testId.substring(0, testId.lastIndexOf("#")), false,
|
||||
TestNGLauncher.class.getClassLoader()).getName();
|
||||
}
|
||||
|
||||
private static String getMethodName(String clazz) {
|
||||
return clazz.substring(clazz.lastIndexOf("#") + 1);
|
||||
private static String getMethodName(String testId) {
|
||||
return testId.substring(testId.lastIndexOf("#") + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,19 +27,19 @@ public class TestNGListener
|
|||
|
||||
@Override
|
||||
public void onTestStart(ITestResult result) {
|
||||
TestRunnerMessageHelper.testStarted(result.getTestClass().getName() + "#" + result.getName());
|
||||
TestRunnerMessageHelper.testStarted(createTestName(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTestSuccess(ITestResult result) {
|
||||
final long duration = result.getEndMillis() - result.getStartMillis();
|
||||
TestRunnerMessageHelper.testFinished(result.getTestClass().getName() + "#" + result.getName(), duration);
|
||||
TestRunnerMessageHelper.testFinished(createTestName(result), duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTestFailure(ITestResult result) {
|
||||
final long duration = result.getEndMillis() - result.getStartMillis();
|
||||
TestRunnerMessageHelper.testFailed(result.getTestClass().getName() + "#" + result.getName(),
|
||||
TestRunnerMessageHelper.testFailed(createTestName(result),
|
||||
result.getThrowable(), duration);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class TestNGListener
|
|||
onTestFailure(result);
|
||||
return;
|
||||
}
|
||||
TestRunnerMessageHelper.testIgnored(result.getTestClass().getName() + "#" + result.getName());
|
||||
TestRunnerMessageHelper.testIgnored(createTestName(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,6 +65,24 @@ public class TestNGListener
|
|||
onTestFailure(result);
|
||||
}
|
||||
|
||||
private String createTestName(ITestResult result) {
|
||||
final String className = result.getTestClass().getName();
|
||||
final String methodName = result.getMethod().getMethodName();
|
||||
final StringBuilder params = new StringBuilder();
|
||||
|
||||
for (final Class<?> paramClazz : result.getMethod().getParameterTypes()) {
|
||||
params.append(paramClazz.getSimpleName().replaceAll("<.*?>", ""));
|
||||
params.append(", ");
|
||||
}
|
||||
|
||||
// Remove the last ", "
|
||||
if (params.length() > 0) {
|
||||
params.delete(params.length() - 2, params.length());
|
||||
}
|
||||
|
||||
return className + "#" + methodName + "(" + params.toString() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(ITestContext context) {
|
||||
}
|
||||
|
@ -82,7 +100,8 @@ public class TestNGListener
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationSuccess(ITestResult itr) {}
|
||||
public void onConfigurationSuccess(ITestResult itr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationFailure(ITestResult result) {
|
||||
|
@ -90,5 +109,6 @@ public class TestNGListener
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationSkip(ITestResult result) {}
|
||||
public void onConfigurationSkip(ITestResult result) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public class TestNGRunner {
|
|||
// backward compatibility
|
||||
testNG.addListener((ITestListener) listener);
|
||||
}
|
||||
|
||||
|
||||
testNG.setXmlSuites(Collections.singletonList(suite));
|
||||
testNG.run();
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class TestNGRunner {
|
|||
final XmlTest test = new XmlTest(suite);
|
||||
test.setName("TestNGTest-" + UUID.randomUUID().toString());
|
||||
final List<XmlClass> classes = new ArrayList<>();
|
||||
for (final Entry<String, List<String>> entry: map.entrySet()) {
|
||||
for (final Entry<String, List<String>> entry : map.entrySet()) {
|
||||
classes.add(createClass(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
test.setXmlClasses(classes);
|
||||
|
@ -59,8 +59,8 @@ public class TestNGRunner {
|
|||
final XmlClass xmlClass = new XmlClass(clazz);
|
||||
if (methods.size() != 0) {
|
||||
final List<XmlInclude> includes = new ArrayList<>();
|
||||
for (final String method: methods) {
|
||||
includes.add(new XmlInclude(method));
|
||||
for (final String method : methods) {
|
||||
includes.add(new XmlInclude(method.replaceAll("\\(.*\\)", "")));
|
||||
}
|
||||
xmlClass.setIncludedMethods(includes);
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -69,7 +69,7 @@
|
|||
"./server/junit-vintage-engine_5.9.0.jar",
|
||||
"./server/org.apiguardian.api_1.1.2.jar",
|
||||
"./server/org.eclipse.jdt.junit4.runtime_1.3.0.v20220609-1843.jar",
|
||||
"./server/org.eclipse.jdt.junit5.runtime_1.1.0.v20220715-1030.jar",
|
||||
"./server/org.eclipse.jdt.junit5.runtime_1.1.100.v20220907-0450.jar",
|
||||
"./server/org.opentest4j_1.2.0.v20211018-1956.jar",
|
||||
"./server/com.microsoft.java.test.plugin-0.37.1.jar"
|
||||
],
|
||||
|
|
|
@ -184,6 +184,69 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
}
|
||||
|
||||
protected getTestId(message: string): string {
|
||||
if (message.includes('engine:junit5') || message.includes('engine:junit-jupiter') || message.includes('engine:jqwik')) {
|
||||
return this.getTestIdForJunit5Method(message);
|
||||
} else {
|
||||
return this.getTestIdForNonJunit5Method(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected getTestIdForJunit5Method(message: string): string {
|
||||
const classId: string = 'class:';
|
||||
const nestedClassId: string = 'nested-class:';
|
||||
const methodId: string = 'method:';
|
||||
// Property id is for jqwik
|
||||
const propertyId: string = 'property:';
|
||||
const testTemplateId: string = 'test-template:';
|
||||
|
||||
// We're expecting something like:
|
||||
// [engine:junit5]/[class:com.example.MyTest]/[method:myTest]/[test-template:myTest(String\, int)]
|
||||
const parts: string[] = message.split('/');
|
||||
|
||||
let className: string = '';
|
||||
let methodName: string = '';
|
||||
|
||||
if (!parts || parts.length === 0) {
|
||||
// The pattern doesn't match what we're expecting, so we'll go ahead and defer to the non JUnit5 method.
|
||||
return this.getTestIdForNonJunit5Method(message);
|
||||
}
|
||||
|
||||
parts.forEach((part: string) => {
|
||||
// Remove the leading and trailing brackets.
|
||||
part = part.trim().replace(/\[/g, '').replace(/\]/g, '');
|
||||
|
||||
if (part.startsWith(classId)) {
|
||||
className = part.substring(classId.length);
|
||||
} else if (part.startsWith(methodId)) {
|
||||
const rawMethodName: string = part.substring(methodId.length);
|
||||
// If the method name exists then we want to include the '#' qualifier.
|
||||
methodName = `#${this.getJUnit5MethodName(rawMethodName)}`;
|
||||
} else if (part.startsWith(nestedClassId)) {
|
||||
const nestedClassName: string = part.substring(nestedClassId.length);
|
||||
className = `${className}$${nestedClassName}`;
|
||||
} else if (part.startsWith(testTemplateId)) {
|
||||
const rawMethodName: string = part.substring(testTemplateId.length)
|
||||
.replace('\\,', ',')
|
||||
.replace(' ', '');
|
||||
// If the method name exists then we want to include the '#' qualifier.
|
||||
methodName = `#${this.getJUnit5MethodName(rawMethodName)}`;
|
||||
} else if (part.startsWith(propertyId)) {
|
||||
const rawMethodName: string = part.substring(propertyId.length)
|
||||
.replace('\\,', ',')
|
||||
.replace(' ', '');
|
||||
// If the method name exists then we want to include the '#' qualifier.
|
||||
methodName = `#${this.getJUnit5MethodName(rawMethodName)}`;
|
||||
}
|
||||
});
|
||||
|
||||
if (className) {
|
||||
return `${this.projectName}@${className}${methodName}`;
|
||||
} else {
|
||||
return `${this.projectName}@${message}`;
|
||||
}
|
||||
}
|
||||
|
||||
protected getTestIdForNonJunit5Method(message: string): string {
|
||||
/**
|
||||
* The following regex expression is used to parse the test runner's output, which match the following components:
|
||||
* '(?:@AssumptionFailure: |@Ignore: )?' - indicate if the case is ignored due to assumption failure or disabled
|
||||
|
@ -206,6 +269,27 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
return `${this.projectName}@${message}`;
|
||||
}
|
||||
|
||||
protected getJUnit5MethodName(rawName: string): string {
|
||||
// Let's start by grabbing the text between the parentheses.
|
||||
let rawParamsString: string = rawName.substring(rawName.indexOf('(') + 1, rawName.indexOf(')'));
|
||||
// We're going to replace any '$' characters with '.' characters to simplify the following logic.
|
||||
// NOTE: you will get '$' characters in the name if you have a nested class.
|
||||
rawParamsString = rawParamsString.replace(/\$/g, '.');
|
||||
|
||||
const params: string[] = rawParamsString.split(',');
|
||||
let paramString: string = '';
|
||||
params.forEach((param: string) => {
|
||||
paramString += `${param.substring(param.lastIndexOf('.') + 1)}, `;
|
||||
});
|
||||
// We want to remove the final comma.
|
||||
if (paramString.length > 0) {
|
||||
paramString = paramString.substring(0, paramString.length - 2);
|
||||
}
|
||||
|
||||
const methodName: string = rawName.substring(0, rawName.indexOf('('));
|
||||
return `${methodName}(${paramString})`;
|
||||
}
|
||||
|
||||
private setCurrentState(testItem: TestItem, resultState: TestResultState, duration: number): void {
|
||||
this.currentStates.set(testItem, { resultState, duration });
|
||||
}
|
||||
|
@ -248,7 +332,7 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
const result: RegExpMatchArray | null = message.match(regExp);
|
||||
if (result && result.length > 6) {
|
||||
const index: string = result[0];
|
||||
const testId: string = this.getTestId(result[1]);
|
||||
const testId: string = this.getTestId(result[result.length - 1]);
|
||||
const isSuite: boolean = result[2] === 'true';
|
||||
const testCount: number = parseInt(result[3], 10);
|
||||
const isDynamic: boolean = result[4] === 'true';
|
||||
|
@ -264,23 +348,7 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
if (parent) {
|
||||
const parentData: ITestItemData | undefined = dataCache.get(parent);
|
||||
if (parentData?.testLevel === TestLevel.Method) {
|
||||
testItem = updateOrCreateTestItem(parent, {
|
||||
children: [],
|
||||
uri: parent.uri?.toString(),
|
||||
range: parent.range,
|
||||
jdtHandler: parentData.jdtHandler,
|
||||
fullName: parentData.fullName,
|
||||
label: this.getTestMethodName(displayName),
|
||||
// prefer uniqueId, as it does not change when re-running only a single invocation:
|
||||
id: uniqueId ? `${INVOCATION_PREFIX}${uniqueId}`
|
||||
: `${INVOCATION_PREFIX}${parent.id}[#${parent.children.size + 1}]`,
|
||||
projectName: parentData.projectName,
|
||||
testKind: parentData.testKind,
|
||||
testLevel: TestLevel.Invocation,
|
||||
uniqueId,
|
||||
// We will just create a string padded with the character "a" to provide easy sorting.
|
||||
sortText: ''.padStart(parent.children.size + 1, 'a')
|
||||
});
|
||||
testItem = this.enlistDynamicMethodToTestMapping(testItem, parent, parentData, displayName, uniqueId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -336,6 +404,28 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
// Leaving this public so that it can be mocked when testing.
|
||||
public enlistDynamicMethodToTestMapping(testItem: TestItem | undefined, parent: TestItem, parentData: ITestItemData, displayName: string, uniqueId: string | undefined): TestItem {
|
||||
testItem = updateOrCreateTestItem(parent, {
|
||||
children: [],
|
||||
uri: parent.uri?.toString(),
|
||||
range: parent.range,
|
||||
jdtHandler: parentData.jdtHandler,
|
||||
fullName: parentData.fullName,
|
||||
label: this.getTestMethodName(displayName),
|
||||
// prefer uniqueId, as it does not change when re-running only a single invocation:
|
||||
id: uniqueId ? `${INVOCATION_PREFIX}${uniqueId}`
|
||||
: `${INVOCATION_PREFIX}${parent.id}[#${parent.children.size + 1}]`,
|
||||
projectName: parentData.projectName,
|
||||
testKind: parentData.testKind,
|
||||
testLevel: TestLevel.Invocation,
|
||||
uniqueId,
|
||||
// We will just create a string padded with the character "a" to provide easy sorting.
|
||||
sortText: ''.padStart(parent.children.size + 1, 'a')
|
||||
});
|
||||
return testItem;
|
||||
}
|
||||
|
||||
private async tryAppendMessage(item: TestItem, testMessage: TestMessage, testState: TestResultState): Promise<void> {
|
||||
if (this.testMessageLocation) {
|
||||
testMessage.location = this.testMessageLocation;
|
||||
|
@ -373,6 +463,10 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
|
|||
* Get the test item label without the codicon prefix.
|
||||
*/
|
||||
private getLabelWithoutCodicon(name: string): string {
|
||||
if (name.includes('#')) {
|
||||
name = name.substring(name.indexOf('#') + 1);
|
||||
}
|
||||
|
||||
const result: RegExpMatchArray | null = name.match(/(?:\$\(.+\) )?(.*)/);
|
||||
if (result?.length === 2) {
|
||||
return result[1];
|
||||
|
|
|
@ -27,8 +27,8 @@ suite('JUnit Runner Analyzer Tests for JUnit5 Parallel Tests', () => {
|
|||
setup(() => {
|
||||
testController = tests.createTestController('testController', 'Mock Test');
|
||||
const testItemParent = generateTestItem(testController, 'junit@junit5.ParallelExecutionTest', TestKind.JUnit5, new Range(0, 0, 0, 0), undefined, 'ParallelExecutionTest.java');
|
||||
testItem1 = generateTestItem(testController, 'junit@junit5.ParallelExecutionTest#test1', TestKind.JUnit5, new Range(1, 0, 1, 0), undefined, 'ParallelExecutionTest.java');
|
||||
testItem2 = generateTestItem(testController, 'junit@junit5.ParallelExecutionTest#test2', TestKind.JUnit5, new Range(2, 0, 2, 0), undefined, 'ParallelExecutionTest.java');
|
||||
testItem1 = generateTestItem(testController, 'junit@junit5.ParallelExecutionTest#test1()', TestKind.JUnit5, new Range(1, 0, 1, 0), undefined, 'ParallelExecutionTest.java');
|
||||
testItem2 = generateTestItem(testController, 'junit@junit5.ParallelExecutionTest#test2()', TestKind.JUnit5, new Range(2, 0, 2, 0), undefined, 'ParallelExecutionTest.java');
|
||||
testItemParent.children.add(testItem1);
|
||||
testItemParent.children.add(testItem2);
|
||||
const testRunRequest = new TestRunRequest([testItemParent], []);
|
||||
|
|
|
@ -228,7 +228,7 @@ java.lang.RuntimeException
|
|||
});
|
||||
|
||||
test("test diff with line separators", () => {
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestAnnotation#shouldFail2', TestKind.JUnit5, new Range(8, 0, 10, 0));
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestAnnotation#shouldFail2()', TestKind.JUnit5, new Range(8, 0, 10, 0));
|
||||
const testRunRequest = new TestRunRequest([testItem], []);
|
||||
const testRun = testController.createTestRun(testRunRequest);
|
||||
const startedSpy = sinon.spy(testRun, 'started');
|
||||
|
@ -283,63 +283,80 @@ org.junit.ComparisonFailure: expected:<hello
|
|||
assert.strictEqual(testMessage.location?.range.start.line, 8);
|
||||
});
|
||||
|
||||
// The following test also tests JUnit 5 test classes that contain two
|
||||
// methods with the same name but different signatures.
|
||||
test("test JUnit 5's display name", () => {
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestAnnotation#test', TestKind.JUnit5, new Range(8, 0, 10, 0));
|
||||
let testRunRequest = new TestRunRequest([testItem], []);
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestAnnotation#test()', TestKind.JUnit5, new Range(8, 0, 10, 0));
|
||||
const testItemWithParams = generateTestItem(testController, 'junit@junit5.TestAnnotation#test(int)', TestKind.JUnit5, new Range(14, 0, 16, 0));
|
||||
let testRunRequest = new TestRunRequest([testItem, testItemWithParams], []);
|
||||
let testRun = testController.createTestRun(testRunRequest);
|
||||
let testRunnerOutput = `%TESTC 1 v2
|
||||
%TSTTREE2,junit5.TestAnnotation,true,1,false,1,TestAnnotation,,[engine:junit-jupiter]/[class:junit5.TestAnnotation]
|
||||
%TSTTREE2,junit5.TestAnnotation,true,2,false,1,TestAnnotation,,[engine:junit-jupiter]/[class:junit5.TestAnnotation]
|
||||
%TSTTREE3,test(junit5.TestAnnotation),false,1,false,2,hi,,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[method:test()]
|
||||
%TSTTREE4,test(junit5.TestAnnotation),true,0,false,2,hi_with_params,int,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[test-template:test(int)]
|
||||
%TESTS 3,test(junit5.TestAnnotation)
|
||||
|
||||
%TESTE 3,test(junit5.TestAnnotation)
|
||||
|
||||
%TSTTREE5,test(junit5.TestAnnotation),false,1,true,4,[1] 1,int,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[test-template:test(int)]/[test-template-invocation:#1]
|
||||
%TESTS 5,test(junit5.TestAnnotation)
|
||||
%TESTE 5,test(junit5.TestAnnotation)
|
||||
%RUNTIME86`;
|
||||
|
||||
let runnerContext: IRunTestContext = {
|
||||
isDebug: false,
|
||||
kind: TestKind.JUnit5,
|
||||
projectName: 'junit',
|
||||
testItems: [testItem],
|
||||
testItems: [testItem, testItemWithParams],
|
||||
testRun: testRun,
|
||||
workspaceFolder: workspace.workspaceFolders?.[0]!,
|
||||
};
|
||||
|
||||
let analyzer = new JUnitRunnerResultAnalyzer(runnerContext);
|
||||
let analyzer = new JUnitRunnerResultAnalyzer(runnerContext)
|
||||
// We need to stub this method to avoid isssues with the TestController
|
||||
// not being set up in the non-test version of the utils file.
|
||||
const stub = sinon.stub(analyzer, "enlistDynamicMethodToTestMapping");
|
||||
stub.returnsArg(0);
|
||||
analyzer.analyzeData(testRunnerOutput);
|
||||
|
||||
assert.strictEqual(testItem.description, 'hi');
|
||||
assert.strictEqual(testItemWithParams.description, 'hi_with_params');
|
||||
|
||||
// Remove the @DisplayName annotation
|
||||
testRunRequest = new TestRunRequest([testItem], []);
|
||||
testRunRequest = new TestRunRequest([testItem, testItemWithParams], []);
|
||||
testRun = testController.createTestRun(testRunRequest);
|
||||
testRunnerOutput = `%TESTC 1 v2
|
||||
%TSTTREE2,junit5.TestAnnotation,true,1,false,1,TestAnnotation,,[engine:junit-jupiter]/[class:junit5.TestAnnotation]
|
||||
%TSTTREE2,junit5.TestAnnotation,true,2,false,1,TestAnnotation,,[engine:junit-jupiter]/[class:junit5.TestAnnotation]
|
||||
%TSTTREE3,test(junit5.TestAnnotation),false,1,false,2,test(),,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[method:test()]
|
||||
%TSTTREE4,test(junit5.TestAnnotation),true,0,false,2,test(int),int,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[test-template:test(int)]
|
||||
%TESTS 3,test(junit5.TestAnnotation)
|
||||
|
||||
%TESTE 3,test(junit5.TestAnnotation)
|
||||
|
||||
%TSTTREE5,test(junit5.TestAnnotation),false,1,true,4,[1] 1,int,[engine:junit-jupiter]/[class:junit5.TestAnnotation]/[test-template:test(int)]/[test-template-invocation:#1]
|
||||
%TESTS 5,test(junit5.TestAnnotation)
|
||||
%TESTE 5,test(junit5.TestAnnotation)
|
||||
%RUNTIME81`;
|
||||
|
||||
runnerContext = {
|
||||
isDebug: false,
|
||||
kind: TestKind.JUnit5,
|
||||
projectName: 'junit',
|
||||
testItems: [testItem],
|
||||
testItems: [testItem, testItemWithParams],
|
||||
testRun: testRun,
|
||||
workspaceFolder: workspace.workspaceFolders?.[0]!,
|
||||
};
|
||||
|
||||
analyzer = new JUnitRunnerResultAnalyzer(runnerContext);
|
||||
// We need to stub this method to avoid isssues with the TestController
|
||||
// not being set up in the non-test version of the utils file.
|
||||
sinon.stub(analyzer, "enlistDynamicMethodToTestMapping");
|
||||
analyzer.analyzeData(testRunnerOutput);
|
||||
|
||||
assert.strictEqual(testItem.description, '');
|
||||
assert.strictEqual(testItemWithParams.description, '');
|
||||
});
|
||||
|
||||
test("test diff is not duplicated when failing assertion is extracted", () => {
|
||||
const range = new Range(9, 0, 11, 0);
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestWithExtractedEqualityAssertion#test', TestKind.JUnit5, range, undefined, 'TestWithExtractedEqualityAssertion.java');
|
||||
const testItem = generateTestItem(testController, 'junit@junit5.TestWithExtractedEqualityAssertion#test()', TestKind.JUnit5, range, undefined, 'TestWithExtractedEqualityAssertion.java');
|
||||
const testRunRequest = new TestRunRequest([testItem], []);
|
||||
const testRun = testController.createTestRun(testRunRequest);
|
||||
const startedSpy = sinon.spy(testRun, 'started');
|
||||
|
|
|
@ -18,7 +18,7 @@ export function generateTestItem(testController: TestController, id: string, tes
|
|||
|
||||
const projectName = id.substring(0, id.indexOf('@'));
|
||||
const fullName = id.substring(id.indexOf('@') + 1);
|
||||
const label = id.substring(id.indexOf('#') + 1) + '()';
|
||||
const label = testKind === TestKind.JUnit5 ? id : id.substring(id.indexOf('#') + 1) + '()';
|
||||
|
||||
const testItem = testController.createTestItem(id, label, Uri.file(uri));
|
||||
testItem.range = range || new Range(0, 0, 0, 0);
|
||||
|
|
|
@ -47,6 +47,12 @@
|
|||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>7.7.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,29 +1,35 @@
|
|||
package junit4;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class ParameterizedTest {
|
||||
private int input;
|
||||
private int expected;
|
||||
|
||||
@Parameter
|
||||
public int expected;
|
||||
public ParameterizedTest(int input, int expected) {
|
||||
this.input = input;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
@Parameters
|
||||
public static Collection<Integer> data(){
|
||||
return Arrays.asList(1, 2);
|
||||
@Parameterized.Parameters
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{ 0, 0 },
|
||||
{ 1, 1 },
|
||||
{ 2, 4 }
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertEquals(expected, 1);
|
||||
public void testSquare() {
|
||||
assertEquals(expected, input * input);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,25 @@
|
|||
package junit5;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
public class AppTest {
|
||||
@Test
|
||||
void testGetGreeting() {
|
||||
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1, 2",
|
||||
"1, 1"
|
||||
})
|
||||
public void testGetGreeting(int first, int second) throws Exception {
|
||||
if (second == 2) {
|
||||
fail("second should not be 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package testng;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class CharUtilsTest {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] ValidDataProvider() {
|
||||
return new Object[][] {
|
||||
{ 'A', 65 }, { 'a', 97 },
|
||||
{ 'B', 66 }, { 'b', 98 },
|
||||
{ 'C', 67 }, { 'c', 99 },
|
||||
{ 'D', 68 }, { 'd', 100 },
|
||||
{ 'Z', 90 }, { 'z', 122 },
|
||||
{ '1', 49 }, { '9', 517 }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "ValidDataProvider")
|
||||
public void CharToASCIITest(final char character, final int ascii) {
|
||||
int result = (int) character;
|
||||
Assert.assertEquals(result, ascii);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void CharToASCIITest() {
|
||||
Assert.assertEquals(1, 2);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче