How to call a TESTNG class from a Springboot based selenium project - spring-boot

Running Testng class from Springboot application gives an error
I have a Springboot based Selenium Testng project.
When I do a Maven configuration like mvn clean package -Dtests= testng is file name of xml file, it works seemlessly.
Now I have a scenario where I need to get the testsuite name which user likes to test on commandline and use that and run the test suite.
I have the following in the #SpringBootApplication main method. Assuming I get the test suite thru commandline, I have this code, but the springboot servers keeps running in infinite without running the tests.
How could I fix it.
#SpringBootApplication
public class MyAutomationApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyAutomationApplication.class, args);
}
public void run(String... args) throws Exception {
System.out.println("Welcome!!");
//assuming i get the InitialLoginTest from commandline, i am passing the CLASS NAME to classes.add(new XmlClass("InitialLoginTest"));
TestNG tng = new TestNG();
XmlSuite suite = new XmlSuite();
suite.setName("Appium Test suite");
XmlTest test = new XmlTest(suite);
test.setName("Sample Test");
List<XmlClass> classes = new ArrayList();
classes.add(new XmlClass("InitialLoginTest"));
test.setXmlClasses(classes);
List<XmlSuite> suites = new ArrayList();
suites.add(suite);
tng.setXmlSuites(suites);
tng.run();
}
}
#SpringBootTest
public class InitialLoginTest {
#Test
void loading() {
System.out.println("In InitialLoginTest!!");
}
}

Related

tun unit tests in parallel and other test sequentially in the same run spring boot kotlin

i am having an issue to understand how can i run all the unit tests in my boot spring application(kotlin) in parallel while the springBootTests and the dataJpaTests will run one after the other(becouse they are failing due to shared context where running in parallel),
my application structure is separated to different models and each model have it's unit,springBootTests and dataJpaTets, like this:
-module 1:
unit test 1
unit test 2
data jpa test 1
data jpa test 2
spring boot test1
-module 2:
unit test 1
unit test 2
unit test 3
data jpa test 1
spring boot test1
i used the following properties from https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution:
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent //tests in each class run in parallel
junit.jupiter.execution.parallel.mode.classes.default = concurrent //classes run in parallel
but it is not helping becouse there is no way to exclude the springBoot and dataJpa tests from the parallization.
also,i tried to put the #Execution(SAME_THREAD) on all the dataJpa and springBoot test but still
the classes itself runed in parallel and test was colliding
*i use --test *test commend to run all the tests together
Spring uses Junit
By default, JUnit Jupiter tests are run sequentially in a single thread.
Running tests in parallel — for example, to speed up execution — is available as an experimental feature since version 5.3
Source: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution
Using pure Junit
#Execution(ExecutionMode.CONCURRENT)
class MyTest {
#Test
void test1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Test1 " + Thread.currentThread().getName());
}
#Test
void test2() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Test 2! " + Thread.currentThread().getName());
}
}
source:
https://stackoverflow.com/a/55244698/3957754
https://www.swtestacademy.com/junit5-parallel-test-execution/
Using spring + maven + junit
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
</configuration>
</plugin>
</build>
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = Spring5JUnit4ConcurrentTest.SimpleConfiguration.class)
public class Spring5JUnit4ConcurrentTest implements ApplicationContextAware, InitializingBean {
#Configuration
public static class SimpleConfiguration {}
private ApplicationContext applicationContext;
private boolean beanInitialized = false;
#Override
public void afterPropertiesSet() throws Exception {
this.beanInitialized = true;
}
#Override
public void setApplicationContext(
final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
#Test
void test1A() {
System.out.println(Thread.currentThread().getName()+" => test1A");
}
#Test
void test1B() {
System.out.println(Thread.currentThread().getName()+" => test1B");
}
#Test
void testC() {
System.out.println(Thread.currentThread().getName()+" => test1C");
}
}
Sources:
https://www.baeldung.com/spring-5-concurrent-tests
https://javabydeveloper.com/junit-5-parallel-tests-execution-and-resourcelock-examples/
Running junit tests in parallel in a Maven build?
Running junit testcases in parallel using maven
Simple tests are "almost parallel"
According to this and my tests, simple junit tests are executed almost parallel
public class Hello1Test {
#Test
public void myTest() throws Exception {
System.out.println(new Date());
assertTrue(true);
}
}
mvn test
NOTE: If you add some Thread related in the test, they are executed sequentially
#Test
public void myTest() throws Exception {
System.out.println(new Date());
Thread.sleep(2000);
assertTrue(true);
}
Exclude some tests
According to this you could use -Dtest to pick or exclude specific tests
mvn test -q
run all tests
mvn test -q -Dtest='Hello1*'
run only test with name Hello1*
mvn test -q -Dtest='!Hello1*, !Hello2*'
run all tests except Hello1* and Hello2*
Tips
Use the shell, it never lies
According to your ide (eclipse or intellij), you should be able to configure jvm args like : mvn test -q -Dtest
Add date and test name to the log to verify if they are parallel or sequential
Create a minimal reproducible project to help you. Example: https://github.com/jrichardsz/spring-boot-templates/tree/master/011-filter-tests

How to Unit test Spring-Boot Application main() method to get Jacoco test coverage

How to Unit test Spring-Boot Application main() method with SpringApplication.run() . I am wondering if it is possible to get Jacoco test coverage on this class. (Otherwise I will exclude it)
This question is similar, but not the same, as this question: Spring Boot, test main application class
I am using mockito-core 3.8 and mockito-inline.
This test code works for me but Jacoco does not pick it up as test coverage:
#SpringBootTest
#ActiveProfiles("test")
public class AutowireTest {
private static final String ARG = "";
private static final String[] ARGS = new String[]{ARG};
#Autowired
ConfigurableApplicationContext context;
#Test
public void main() {
try (MockedStatic<Application> appStatic = Mockito.mockStatic(Application.class);
MockedStatic<SpringApplication> springStatic = Mockito.mockStatic(
SpringApplication.class)) {
appStatic.when(() -> Application.main(ARGS))
.thenCallRealMethod();
springStatic.when(() -> SpringApplication.run(Application.class, ARGS))
.thenReturn(context);
// when
Application.main(ARGS);
//then
appStatic.verify(times(1),
() -> Application.main(ARGS));
springStatic.verify(times(1),
() -> SpringApplication.run(Application.class, ARGS));
}
}
}
Is Jacoco not able to show coverage on static methods?

Spring boot + cucumber in main scope. Can I autowire a step definition?

I believe this is a very particular case, but I am building some cucumber tests for some third-party applications we use.
Since I am not really testing my own application, I created a maven project and configured cucumber to run in the main folder (not the test folder).
This is my entrypoint class:
#SpringBootApplication
public class ExecutableMain implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(ExecutableMain.class, args);
}
#Override
public void run(String... args) {
// args logic...
JUnitCore.runClasses(MyCucumberTest.class);
}
}
And my test class:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty", "html:target/cucumber", "json:target/cucumber/cucumber.json"},
glue = {"cucumber.app", "cucumber.steps"}
)
public class MyCucumberTest {
#AfterClass
public static void tearDown(){
// quit the browser
}
}
This currently works fine, but I want to add spring features to my tests.
Specifically, I want to autowire something in my cucumber steps.
Stepdefs:
public class MyStepdefs {
#Autowired
private ConfigProperties properties;
#Given("^Something")
public void example() {
//...
}
I searched around and found people saying I should add the ContextConfiguration annotation in the steps. I did it like so:
#ContextConfiguration(classes = ExecutableMain.class, loader = SpringBootContextLoader.class)
public class MyStepdefs {
But this resulted in a loop during start up.
Can I achieve what I need?
Ok, so I got it to work following https://stackoverflow.com/a/37586547/1031162
Basically I changed:
#ContextConfiguration(classes = ExecutableMain.class, loader = SpringBootContextLoader.class)
To:
#ContextConfiguration(classes = ExecutableMain.class, initializers = ConfigFileApplicationContextInitializer.class)
I am not 100% sure how/why it worked, but it did.

Run another project's web service before start tests

IntelliJ project has two modules: Spring Data Rest app and client. Both apps are Spring bootable apps. I made a lot of tests at client and now before every test iteration I have to run the rest service manually.
Test class looks like that:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {BusinessRepositoryImpl.class})
public class BusinessLogoRepositoryTest {
..
}
Here is the service:
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
So the question is if it's possible somehow to add the context of service to test class and run the service before test's start.
You can create a TestSuite with 2 methods annotated with #BeforeClass and #AfterClass to start the service before the tests and stop it after the tests are done.
Draft code to visualize :) what I mean is below.
#RunWith(SpringJUnit4ClassRunner.class)
#SuiteClasses({UnitTest1.class, UnitTest2.class, ... })
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class TestSuite {
#BeforeClass
public void start() throws Exception {
SpringApplication.run(Application.class, args);
}
#AfterClass
public void start() throws Exception {
SpringApplication.shutdown();
}
}

JUnit Test cases failing while running using Maven but works with Eclipse

I have a Junit test case which doesn't work if I run using Maven. But the same test case works when I run using Eclipse.
My Junit class is like this.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/test-config.xml"} )
public class TestDaoImpl {
private final static Logger logger = Logger.getLogger(TestDaoImpl.class);
#Autowired
private MyDaoImpl myDao;
#Test
public void testMyDao() throws Exception {
logger.info("Called testMyDao()================");
// here myDao is null and throwing NullPointerException in sunfire log.
// But this works when I run using Eclipse.
List<MyObj> objList = myDao.getList();
}
#Test
public void testMyCode() throws Exception {
logger.info("Called testMyCode()================");
// this test case works with Maven
List<MyObj> objList = MyClass.getList();
}
}
The sunfire plugin was missing. When added it started working.

Resources