In my project, I have acceptance tests which take a long time to run. When I add new features to the code and write new tests, I want to skip some existing test cases for the sake of time. I am using Spring 3 and junit 4 using SpringJUnit4ClassRunner. My idea is to create an annotation (#Skip or something) for the test class. I am guessing I would have to modify the runner to look for this annotation and determine from system properties if a test class should be included while testing. My question is, is this easily done? Or am I missing an existing functionality somewhere which will help me?
Thanks.
Eric
Annotate your class (or unit test methods) with #Ignore in Junit 4 and #Disabled in Junit 5 to prevent the annotated class or unit test from being executed.
Ignoring a test class:
#Ignore
public class MyTests {
#Test
public void test1() {
assertTrue(true);
}
}
Ignoring a single unit test;
public class MyTests {
#Test
public void test1() {
assertTrue(true);
}
#Ignore("Takes too long...")
#Test
public void longRunningTest() {
....
}
#Test
public void test2() {
assertTrue(true);
}
}
mvn install -Dmaven.test.skip=true
so you can build your project without test,
mvn -Dtest=TestApp1 test
you can just add the name of your application and you can test it.
I use Spring profiles to do this. In your test, autowire in the Spring Environment:
#Autowired
private Environment environment;
In tests you don't want to run by default, check the active profiles and return immediately if the relevant profile isn't active:
#Test
public void whenSomeCondition_somethingHappensButReallySlowly() throws Exception{
if (Arrays.stream(environment.getActiveProfiles()).noneMatch(name -> name.equalsIgnoreCase("acceptance"))) {
return;
}
// Real body of your test goes here
}
Now you can run your everyday tests with something like:
> SPRING_PROFILES_ACTIVE=default,test gradlew test
And when you want to run your acceptance tests, something like:
> SPRING_PROFILES_ACTIVE=default,test,acceptance gradlew test
Of course that's just an example command line assuming you use Gradle wrapper to run your tests, and the set of active profiles you use may be different, but the point is you enable / disable the acceptance profile. You might do this in your IDE, your CI test launcher, etc...
Caveats:
Your test runner will report the tests as run, instead of ignored, which is misleading.
Rather than hard code profile names in individual tests, you probably want a central place where they're all defined... otherwise it's easy to lose track of all the available profiles.
Related
Using Jbehave, my runner class extends JUnitStories, I can generate the plain-style report with the following:
#Override
public Configuration configuration() {
Class<? extends Embeddable > embeddableClass = this.getClass();
return new MostUsefulConfiguration().useStoryLoader(new LoadFromClasspath(embeddableClass))
.useStoryControls(new StoryControls().doResetStateBeforeScenario(false).useStoryMetaPrefix("story_").useScenarioMetaPrefix("scenario_"))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
.withDefaultFormats().withFormats(CONSOLE, HTML).withFailureTrace(true)
.withFailureTraceCompression(true));
}
Now I want to integrate JBehave with Serenity for better looking reports ^_^. So I changed my runner class to inherit from SerenityStories instead. After adding dependencies and running via maven, the tests pass. However, the Serenity generated report always sees '0 test scenarios'.
I saw that SerenityStories inherits JUnitStories, and overrides the configuration() method as well.
How can I make Serenity see my test scenarios? Do I need to override the configuration() method differently? And how?
Thank you very much!
I was able to make it work by creating a new maven project instead.
Used the archetype: 'serenity-jbehave-archetype'.
There will be a pre-created & empty runner class that inherits SerenityStories.
I just then merged my files to this new project.
As for the runner class, I've overridden the methods stepsFactory() and storyPaths() to match my steps/stories.
Hope that made sense. Thanks!
The new Spring Shell docs don't seem to provide any examples of how to integration test CLI commands in a Spring Boot context. Any pointers or examples would be appreciated.
The method Shell#evaluate() has been made public and has its very specific responsibility (evaluate just one command) for exactly that purpose. Please create an issue with the project if you feel like we should provide more (A documentation chapter about testing definitely needs to be written)
Here is how I got this working.
You first need to override the default shell application runner to avoid getting stuck in the jline loop. You can do this by defining your own such as:
#Component
public class CliAppRunner implements ApplicationRunner {
public CliAppRunner() {
}
#Override
public void run(ApplicationArguments args) throws Exception {
//do nothing
}
}
Note that you will have to associate this custom Application runner against a "Test" profile so it overrides only during integration testing.
If you want to test a shell command "add 1 3", you then can write a test like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes =CliConfig.class)
public class ShellCommandIntegrationTest {
#Autowired
private Shell shell;
#Test
public void runTest(){
Object result=shell.evaluate(new Input(){
#Override
public String rawText() {
return "add 1 3";
}
});
DefaultResultHandler resulthandler=new DefaultResultHandler();
resulthandler.handleResult(result);
}
}
Note that the above test does not Assert anything. You will probably have to write your own little implementation of the ResultHandler interface that deals with parsing/formatting of the result so that it can be asserted.
Hope it helps.
Spring Shell 2.0.1 depends on Spring Boot 1.5.8, which in turn depends on Spring Framework 4.3.12. This makes researching how to implement tests challenging, since the latest version of Spring Shell does not depend on the latest versions of other Spring libraries. Take a look at my example project, sualeh/spring-shell-2-tests-example which has example unit, functional and integration tests for a sample Spring Shell application.
I have imported a Maven project into IntelliJ 12.1.4.
One of the tests gives each object an id and when run from the command line (or in Eclipse or Netbeans) the unit tests all have the id starting at zero. From within IntelliJ the ids increase without being reset to zero causing my tests to fail.
public class CORE_C {
static AtomicLong globalCounter = new AtomicLong();
final long counter;
public CORE_C() {
counter = globalCounter.getAndIncrement();
}
}
It is my understanding that JUnit invokes each test in its own classloader causing the behaviour I see outside IntelliJ. Is this a bug, or just an option I have not yet set correctly? If the latter, what is the proper fix?
Any unit test the includes a call to SELECT (using LINQ) data from my DBContext throws the following error:
The model backing the 'MyDBContext' context has changed since the
database was created. Either manually delete/update the database, or
call Database.SetInitializer with an IDatabaseInitializer instance.
For example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
Doing a search for that specific error leads me to believe that I need to include the following line in my Global.asax Application_Start method:
System.Data.Entity.Database.SetInitializer<MyDBContext>( null );
This is suppose to fix a similar error when running the application itself. Unfortunately, I don't get this error when I run my application and there doesn't seem to be an Application_Start method for my unit test project. Is there any way to to the unit test project that I'm using a custom database back-end and to ignore any changes that have occurred in it?
I added the unit test project after working on my main project for a while so it's possible I messed it up somehow, but I can't figure out for the life of me what to do. I'm using the built in unit testing in Visual Studio 2010.
There are 2 methods that you could use with the VS unit testing framework allowing you to run some code before and after each test and before and after all the tests contained in the file
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
}
// Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
}
or:
// Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
}
// Use ClassCleanup to run code after all tests in a class have run
[ClassCleanup()]
public static void MyClassCleanup()
{
}
I want to to integration tests against an http server. So far I have only experiences with junit for unit testing.
I have two requirements: The framework must have a maven plugin and the tests cases code must be clean - so no dirty hacks and no boilerplate code.
Plain JUnit is good for unit testings, #Test methods are individual. But for integration testing I have to process several dependant steps which must exchange some kind of state (variables).
I already read:
Can we use JUNIT for Automated Integration Testing? and Passing JUnit data between tests and came to the conclusion that I don't like static fields in unit test and I don't want to use TestNG and add dependency annotations on tests and I don't want to put my test into one long unreadable test method.
I though more about some syntax like:
public class MyIntegrationTest() {
#Step
public void testCreate(Context context) {context.put("foo");}
#Step
public void testUpdate(Context context) {context.get();}
#Step
public void testDelete(Context context) {context.get()}
}
So I want to enhance/use ?Unit in a way that it executes #Step methods with a context instance as argument. The methods must be called by the framework in order and cannot be called individually. In a perfect world, all ?Unit guis would show the #Step like an #Test but this is optional...
Any hints how to do this?
Jan
The first point is to check the Maven Failsafe Plugin which is intended for doing integration tests with Maven. Second you have to name your Integration tests based on the conventions used by Maven FailSafe Plugin after that you should be able to run your integration tests simply with maven (by mvn clean verify).
So this means you have to name your integration test like MyIntegrationIT.java...To define the order of executions you have to use a different framework than JUnit may be TestNG which supports this kind of needs, but you already excluded it. So the questions is what kind of tests would you like to do? Page-flows etc. may be a look at JWebUnit might be look worth...
You might also want to consider http://httpunit.sourceforge.net/. It's useful for checking to see if responses come back from the http server.
However, it doesn't do the #Step functionality. Normally I'd do that by :
#Test
public void MasterTest() {
step1(..);
step2(..);
....
}
public void step1(...){...}
public void step2(...){...}