Maven - Use static variable from src/test to src/main - maven

A simple login and logout selenium test, using pagefactory is created with TestNG and it works fine while running it as a "TestNG" test. I'm migrating it to Maven and came across issues in accessing variables between different classes.
src/main/java
---package:myapp.pages
Homepage.java
LoginPage.java
---package:utilities
CommonUtils.java
DatabaseUtils.java
src/test/java
---package:myapp.test
LoginTest.java (has static variable about test name)
public static String sTestName = "Regression test - Login/Logout"
While using the above variable in LoginPage.java, there is a compilation error. I'm using it as
public static String sName=myapp.test.LoginTest.sTestName;
The compilation error is:
[10,22] package myapp.test does not exist
How to handle this error? Any help would be highly appreciated.

src/main is where your production code lives, src/test is where your test code lives. The production code is to be shipped to the production environment, the test code is not. Hence, the production code should not depend on the test code. Maven enforces this for you (and your IDE will do so accordingly). There should never be a case where your production code needs to depend on something that's only known to the testing code. Now, there are valid scenarios in which you want behavior to be different during tests than it is for production code, and there is many strategies to do so. For example you can use a properties file (and have one with the same name in src/test/resources "magically" override the production one during testing), or use setters to override things just during testing.

Related

Maven JUnit 5: Using JUnit5 tags, run all unit tests by default or run only a specific test suite from the command line

I posted this: Maven JUnit 5: Run all unit tests by default or run only a specific test suite from the command line .
I'm simply posting it again with almost exactly the same title because nothing about my base problem has changed, but I will include what I tried to do with Tags, which are not working for me.
We are upgrading our services to a relatively recent SpringBoot version, along with JUnit 5. We normally run our builds with just "mvn package", which runs all of our unit tests by default.
We also have "component tests", which are run from a separate command line, and which are all specified in a single test suite with a specific name. Before JUnit 5, we would run this with something like:
mvn -Dtest=ComponentTestSuite test
This was working fine with JUnit 4.
The class looks like this:
#Suite
#SelectClasses(<testclassname>.class)
public class ComponentTestSuite {
}
With JUnit 5, this ends up saying "No tests found".
We are using v2.3.12 of Spring-Boot, which by default includes a somewhat older version of JUnit 5. I am overriding those defaults and including v1.8.2 of the junit-platform components and v5.8.2 of the jupiter components.
For the service that I'm testing this with, the test suite only has a single component test (which is unusual). I WAS able to simply replace "ComponentTestSuite" with the name of the component test class, and that would run that single component test.
I noticed this thread: Junit5 test suites with #Suite annotation doesn't execute tests with mvn test command .
Unfortunately, what I found was that changing "-Dtest" to "-Dinclude" simply ran all my default unit tests and ignored the test suite.
So, I was told that I'm "not supposed to do it this way", although it's not clear to me exactly which parts I'm not supposed to do, but I am supposed to use "Tags". Ok, so I tried to use tags.
I also noticed this article: https://www.baeldung.com/junit-filtering-tests , although that article appears to use some deprecated mechanisms, like "#RunWith(JUnitPlatform.class)", so I'm not sure how much I can believe from that article.
I've been trying several variations, and my last attempt is this:
#Suite
#Tag("ComponentTest")
#IncludeTags("ComponentTest")
public class ComponentTestSuite {
}
And I added #Tag("ComponentTest") to my one component test class.
This still doesn't work. I try to run mvn -Dtest=ComponentTestSuite test, and it says "No tests found". If I instead try mvn -Dtests=ComponentTest test that just runs all of my unit tests and ignores my component test suite. If I instead run mvn test -Dgroups=ComponentTest, that gives me another variation of "No tests found" in that it doesn't print that, it just literally executes no tests without giving an error.
Looking at that suite class now, it does seem nonsensical, as it doesn't really "contain" anything anymore, which is unfortunate. It was good to have that list of component test classes in one place. Now, it seems like the suite class is pointless, but I can't get anything to work anyway.
Note that I haven't yet added a "groups" element to my surefire config, and I haven't edited all of my unit tests to add a #Tag("UnitTest") annotation. I've only edited the suite class and the one component test.
Update:
To address a comment, I am specifying the following dependencies (among others):
Version 1.8.2 of
junit-platform-suite
junit-platform-suite-api
junit-platform-launcher
junit-platform-commons
junit-platform-engine
junit-platform-runner
junit-platform-suite-engine
Version 5.8.2 of
junit-jupiter
junit-bom (probably unnecessary)
The entire suite class is this:
import org.junit.jupiter.api.Tag;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
#Suite
#Tag("ComponentTest")
#IncludeTags("ComponentTest")
public class ComponentTestSuite {
}

Prevent AOP(AspectJ) code to be triggered while running test

In my spring boot project, I am using MockMVC to test controller(web) layer. But I also have AOP(AspectJ) logic in my project, when I run unit test for controller with MockMVC, the test also triggers AOP code, how can I prevent AOP code to be triggered while running unit test for controller?
#Test
public void testMyControllerMethod() {
...
// myRequest hits an endpoint function of my controller, there is also AOP intercept the function call, how can I disable AOP to be triggered while running test?
mockMVC.perform(myRequest).andExpect(okStatus)
}
Question is in my code comment :)
I have checked this answer, I understand to use the if() expression, but I don't get TestMode.ACTIVE, there is no such thing in Spring boot. If someone could let me know how to check whether code is running unit test or not at runtime, I would know how to prevent AOP logic run as well.
What I meant in the other answer, as Simon already tried to explain to you, is something like this:
package de.scrum_master.app;
public class TestMode {
public static boolean ACTIVE = false;
}
But actually there I also listed a few other options such as environment variables and system properties. If I were you I would use one of those because in your Maven or Gradle build it would be very easy to set properties or environment variables via configuration. Your if() pointcut could access those variables.
Especially in the context of Spring there is an even simpler option: a test application configuration. Just provide a configuration without aspects to your tests. That way you can have different configurations for
production environment,
unit tests (no aspects),
integration tests (e.g. with aspects but different from unit test and production).
et cetera.
The advantage here is that you don't need any if() pointcuts or build any other knowledge about test/production environments into your aspects, which is quite ugly. My other answer only shows what you can do, it does not say it is the best solution.

Failed to load ApplicationContext for JUnit test in Hudson Maven, but no issues locally

I've tried just about every configuration I can think of (and reviewed some answers on StackOverflow), but all of our tests show the 'Failed to load ApplicationContext' error when run through Hudson. What is interesting is that some tests appear to run and pass, while some run and fail (as expected), but regardless I'm always getting the errors list for all tests. Here is the basic configuration:
#ContextConfiguration(locations = "classpath:/MyTest-context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class MyTest {
#Autowired
private ApplicationContext applicationContext;
public MyTest() {}
#Test
public void doSomething() {
// Implementation...
}
}
UPDATE:
There appears to be a duplicate set of tests running, one for Emma coverage reporting, and the other the normal tests. It is when the tests run for Emma coverage that they are showing the errors. If I turn off the "emma:emma package" goal so those don't run then I don't get the errors, and the tests appear to run fine. I'm not sure if that helps any.
The answer ended up being close to what gontard was pointing to, which is an issue that was hidden by the way Emma's classloader works. Between my local JUnit tests, what was running in our DEV environment, and what was running in Hudson with Emma, all of them have a different way in which the classloader orders the loading of libraries and classes. I ended up reviewing the stack trace on the test results, and it turns out on my local, a new version of a library was loaded via the POM, but in Hudson Emma was loading an old version of a library first. I had to find and remove the old version, and everything now works fine.

org.scalatest: Global setup (like beforeAllSuites?)

I have a scala application with some test using org.scalatest. These test need some global setup (and teardown), in order to manage the test database.
Please don't tell me my tests should not hit the database and I should do it the Java-DAO-Stub-WTF-Overkill-Way™ :-).
I'm running the tests using SBT, which provides a way to execute code before and after test:
testOptions in Test += Tests.Setup( () => println("Setup") )
testOptions in Test += Tests.Cleanup( () => println("Cleanup") )
Unfortunately I cannot access the classes in question there. Unsurprisingly, importing them into build.sbt does not work either.
Any ideas?
You can use the BeforeAndAfterAll or BeforeAndAfter traits, depending upon your needs.
BeforeAndAfterAll:
Trait that can be mixed into suites that need methods invoked before
and after executing the suite. This trait allows code to be executed
before and/or after all the tests and nested suites of a suite are
run.
So in this instance, you would define a MasterSuite which contains all other Suites/Tests, which extends this trait.
BeforeAndAfter:
Trait that can be mixed into suites that need code executed before and
after running each test. This trait facilitates a style of testing in
which mutable fixture objects held in instance variables are replaced
or reinitialized before each test or suite.

Integration testing against an http server - junit?

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(...){...}

Resources