Better e2e tests coverage

- Add integration tests for e2e samples.
- Add some missing commands for new annotation system.
- Backport #654
- Fixes #655
This commit is contained in:
Janne Valkealahti
2023-02-05 16:21:45 +00:00
parent edfe67c00d
commit 8c7b70b21e
12 changed files with 523 additions and 11 deletions

View File

@@ -167,7 +167,8 @@ public class ErrorHandlingCommands {
return CommandHandlingResult.of("Hi, handled custom exception 3\n", 3);
}
if (e instanceof CustomException4) {
return CommandHandlingResult.of("Hi, handled custom exception\n", 42);
String msg = String.format("Hi, handled custom exception %s\n", e);
return CommandHandlingResult.of(msg, 42);
}
if (e instanceof IllegalArgumentException) {
return CommandHandlingResult.of("Hi, handled illegal exception\n", 42);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 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.
@@ -15,8 +15,11 @@
*/
package org.springframework.shell.samples;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Condition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.shell.samples.standard.ResolvedCommands;
@@ -29,9 +32,10 @@ import org.springframework.shell.test.autoconfigure.ShellTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
@ShellTest
@ShellTest(terminalWidth = 120)
@Import(ResolvedCommands.ResolvedCommandsConfiguration.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class AbstractSampleTests {
@@ -45,6 +49,17 @@ public class AbstractSampleTests {
});
}
protected void assertScreenNotContainsText(BaseShellSession<?> session, String textFound, String textNotFound) {
Condition<String> notCondition = new Condition<>(line -> line.contains(textNotFound),
String.format("Text '%s' not found", textNotFound));
await().atMost(2, TimeUnit.SECONDS).untilAsserted(() -> {
ShellAssertions.assertThat(session.screen()).containsText(textFound);
List<String> lines = session.screen().lines();
assertThat(lines).areNot(notCondition);
});
}
protected BaseShellSession<?> createSession(String command, boolean interactive) {
if (interactive) {
InteractiveShellSession session = client.interactive().run();

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.ArityCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.ArityCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class ArityCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "arity-boolean-default-true")
void defaultBooleanValue(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello true");
}
@ParameterizedTest
@E2ESource(command = "arity-boolean-default-true --overwrite false")
void defaultBooleanValueOverwrite(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello false");
}
@ParameterizedTest
@E2ESource(command = "arity-string-array --arg1 foo bar")
void arityStringArray(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [foo, bar]");
}
@ParameterizedTest
@E2ESource(command = "arity-float-array --arg1 1 2")
void arityFloatArray(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [1.0,2.0]");
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.DefaultValueCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.DefaultValueCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class DefaultValueCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "default-value")
void defaultValue(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello hi");
}
@ParameterizedTest
@E2ESource(command = "default-value-boolean1")
void defaultValueBoolean1(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello false");
}
@ParameterizedTest
@E2ESource(command = "default-value-boolean2")
void defaultValueBoolean2(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello true");
}
@ParameterizedTest
@E2ESource(command = "default-value-boolean3")
void defaultValueBoolean3(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello false");
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;
class E2EArgumentsProvider implements ArgumentsProvider, AnnotationConsumer<E2ESource> {
private E2ESource annotation;
@Override
public void accept(E2ESource annotation) {
this.annotation = annotation;
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
String command = this.annotation.command();
List<Arguments> arguments = new ArrayList<>();
boolean anno = this.annotation.anno();
boolean reg = this.annotation.reg();
if (anno) {
arguments.add(Arguments.of(String.format("e2e %s %s", "anno", command), false));
arguments.add(Arguments.of(String.format("e2e %s %s", "anno", command), true));
}
if (reg) {
arguments.add(Arguments.of(String.format("e2e %s %s", "reg", command), false));
arguments.add(Arguments.of(String.format("e2e %s %s", "reg", command), true));
}
return arguments.stream();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.params.provider.ArgumentsSource;
/**
* JUnit source creating a matrix for command combinations.
*
* @author Janne Valkealahti
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ArgumentsSource(E2EArgumentsProvider.class)
@interface E2ESource {
String command();
boolean anno() default true;
boolean reg() default true;
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.ErrorHandlingCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.ErrorHandlingCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class ErrorHandlingCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw1")
void testErrorHandling1(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hi, handled custom exception");
}
@Disabled("trouble with spring-shell-test")
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw2")
void testErrorHandling2(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException2");
}
@Disabled("trouble with spring-shell-test")
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw3")
void testErrorHandling3(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "java.lang.RuntimeException");
}
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw4")
void testErrorHandling4(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hi, handled illegal exception");
}
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw5")
void testErrorHandling5(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hi, handled custom exception 3");
}
@ParameterizedTest
@E2ESource(command = "error-handling --arg1 throw6")
void testErrorHandling6(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hi, handled custom exception org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException4");
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.HelpOptionCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.HelpOptionCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class HelpOptionCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "help-option-default -h")
void testHelpOptionDefault(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "NAME");
}
@ParameterizedTest
@E2ESource(command = "help-option-exists --help hi", anno = false)
void testHelpOptionExists1(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello hi");
}
@ParameterizedTest
@E2ESource(command = "help-option-exists --myhelp", anno = false)
void testHelpOptionExists2(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "NAME");
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.HiddenCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { Registration.class })
class HiddenCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "hidden-1", anno = false)
void hiddenCommandExecutes(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello from hidden command");
}
@ParameterizedTest
@E2ESource(command = "help", anno = false)
void hiddenNotVisibleInHelp(String command, boolean interactive) {
BaseShellSession<?> session = createSession("help", interactive);
assertScreenNotContainsText(session, "help", "hidden-1");
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.OptionTypeCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.OptionTypeCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class OptionTypeCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "option-type-string --arg1 hi")
void optionTypeString(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello hi");
}
@ParameterizedTest
@E2ESource(command = "option-type-boolean", reg = false)
void optionTypeBooleanWithAnno(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false");
}
@ParameterizedTest
@E2ESource(command = "option-type-boolean", anno = false)
void optionTypeBooleanWithReg(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello arg1=false arg2=true arg3=false arg4=null arg5=true arg6=false");
}
@ParameterizedTest
@E2ESource(command = "option-type-integer --arg1 1 --arg2 2")
void optionTypeInteger(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello '1' '2'");
}
@ParameterizedTest
@E2ESource(command = "option-type-enum --arg1 ONE")
void optionTypeEnum(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello ONE");
}
@ParameterizedTest
@E2ESource(command = "option-type-string-array --arg1 one two")
void optionTypeStringArray(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [one,two]");
}
@ParameterizedTest
@E2ESource(command = "option-type-int-array --arg1 1 2")
void optionTypeIntArray(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [1,2]");
}
@ParameterizedTest
@E2ESource(command = "option-type-string-list --arg1 one two")
void optionTypeStringList(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [one, two]");
}
@ParameterizedTest
@E2ESource(command = "option-type-string-set --arg1 one two")
void optionTypeStringSet(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [one, two]");
}
@ParameterizedTest
@E2ESource(command = "option-type-string-collection --arg1 one two")
void optionTypeStringCollection(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello [one, two]");
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2023 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
*
* https://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.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.OptionalValueCommands.LegacyAnnotation;
import org.springframework.shell.samples.e2e.OptionalValueCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class OptionalValueCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@E2ESource(command = "optional-value")
void optionalValueResolvesToNull(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Hello null");
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.shell.samples.e2e;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.springframework.shell.samples.AbstractSampleTests;
import org.springframework.shell.samples.e2e.RequiredValueCommands.LegacyAnnotation;
@@ -24,16 +23,11 @@ import org.springframework.shell.samples.e2e.RequiredValueCommands.Registration;
import org.springframework.shell.test.ShellTestClient.BaseShellSession;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = {LegacyAnnotation.class, Registration.class})
@ContextConfiguration(classes = { LegacyAnnotation.class, Registration.class })
class RequiredValueCommandsTests extends AbstractSampleTests {
@ParameterizedTest
@CsvSource({
"e2e anno required-value,false",
"e2e reg required-value,false",
"e2e anno required-value,true",
"e2e reg required-value,true"
})
@E2ESource(command = "required-value")
void shouldRequireOption(String command, boolean interactive) {
BaseShellSession<?> session = createSession(command, interactive);
assertScreenContainsText(session, "Missing mandatory option");