how to pass parameters to a test case while running it using Junit Suite - selenium

I want to run multitple Junit tests i have created in a package. Every test needs region and server paramter to load the correct data files. I am using System.getProperty to fetch region and serverdetails for all junit tests. I am not sure how to pass these parameters in a TestSuite Runner. Here is the test case i have created
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ExpenseTests {
private static String server = System.getProperty("server");
private static String region = System.getProperty("region");
#BeforeClass
public static void setup() throws Exception {
SetUp setUp = new SetUp(region, server);
Login(region, server);
CreateClient(region, server);
}
#Test
public void test1_checkexpense() {
// code here
}
#Test
public void test2_addbasicExpense() {
//code here
}
#AfterClass
public static void teardown() throws Exception {
quit(webpage);
}
}
Here is the TestSuite
#RunWith(Suite.class)
#Suite.SuiteClasses({
ExpenseTests.class
AnotherTest.class
})
public class SmokeTestSuite {
}
I can run ExpenseTest using mvn install -Dtest="ExpenseTests" -Dserver="prod" -Dregion="us" but how do i pass region and server details in above SmokeTestSuite?

I think you may use Global variable to pass parameter to all test cases.
Example
public static String server = System.getProperty("server");
public static String region = System.getProperty("region");
Then pass it to all test cases.

Related

JUnit5: Before and After Suite method invocation

I've spent a few days trying to find out a solution, so I know all the basic answers
I've read the documentation, and I know, that #BeforeClass/#AfterClass is replaced with #BeforeAll/#AfterAll, #RunWith no longer exists; superseded by #ExtendWith
I've read all the topics here on the stackoverflow (removed links, since stackoverflow pretends it's a spam:(
I used to run some JUnit4 tests in the suites. Each Suite class Suite1.class, Suite2.class had several #Test methods and #BeforeClass/#AfterClass were running exactly before/after all the testing methods.
#RunWith(StopOnFailureSuite.class)
#Suite.SuiteClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
private static final byte SUITE_NUMBER = 20;
#BeforeClass
public static void setUpClass() {
//some logic for suite setup
}
#AfterClass
public static void tearDownClass() {
//some logic for teardown
}
}
As I wanted to use #ParameterizedTests I need to migrate to JUnit5.
And suddenly I realised, that exact the same behaviour, that used to be in JUnit4 is no more achievable.
[run some custom setup code; run several test classes, which may contain several #Test methods; run some custom tear down code];
Does anybody know (better with examples) an approach to make it with JUnit 5?
Option 1
This code will never execute BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll
#ExtendWith(BeforeAfterSuite.class)
#Suite
#SelectClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
public static final byte SUITE_NUMBER = 20;
}
public class BeforeAfterSuite implements BeforeAllCallback, AfterAllCallback
/*,TestInstancePreConstructCallback, BeforeTestExecutionCallback,
AfterTestExecutionCallback, ExtensionContext.Store.CloseableResource*/ {
private static boolean started = false;
#Override
public void beforeAll(ExtensionContext context) {
if (!started) {
started = true;
//before stuff
}
}
#Override
public void afterAll(ExtensionContext context) throws Exception {
//after all;
}
}
Option 2
I was just curious, how will JUnit treat suite class if I put a test method into it...
This code will execute BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll once, before and after TSuite_20#test
#ExtendWith(BeforeAfterSuite.class)
#Suite
#SelectClasses({
Test1.class,
Test2.class
})
public class TSuite_20 {
public static final byte SUITE_NUMBER = 20;
#Test
public void test() {
}
}
Option 3
We also can apply #ExtendWith(BeforeAfterSuite.class) per Test class which will results in a BeforeAfterSuite#beforeAll and BeforeAfterSuite#afterAll per Test class. (in this example - 2 times).
#ExtendWith(BeforeAfterSuite.class)
public class Test1 {
#Test
public void test11() {
}
#Test
public void test12() {
}
}
#ExtendWith(BeforeAfterSuite.class)
public class Test2 {
#Test
public void test21() {
}
#Test
public void test22() {
}
}
Option 4
I also give a shot for
a Suite class without #ExtendWith() and #BeforeAll + #AfterAll; (as expected nothing happened)`
a Suite class without #ExtendWith() and #BeforeAll + #Test + #AfterAll; (as expected single execution of BeforeAll/AfterAll for the specific Suite class)`
Option 5
Listeners were my last hope to achieve the desired behaviour.
I've created my own impl for LauncherSessionListener, just because I've thought it will allow me to execute smth exactly before tests start.
public class BeforeAfterSuiteLauncher implements LauncherSessionListener {
private static boolean started = false;
#Override
public void launcherSessionOpened(LauncherSession session) {
if (!started) {
started = true;
//before all
}
}
#Override
public void launcherSessionClosed(LauncherSession session) {
//after all
}
}
And I've added also some default impl CompositeLauncherSessionListener
Packages structure screenshot to show Java SPI configuration: LauncherSessionListener
For TestExecutionListener I've added two default impls, just to catch at least one Listener:
org.junit.platform.launcher.listeners.LoggingListener
org.junit.platform.launcher.listeners.SummaryGeneratingListener
and one custom
public class BeforeAfterExecutionListener implements TestExecutionListener {
#Override
public void testPlanExecutionStarted(TestPlan testPlan) {
//before all
}
#Override
public void testPlanExecutionFinished(TestPlan testPlan) {
//after all
}
}
Packages structure screenshot to show Java SPI configuration:TestExecutionListener
And only SummaryGeneratingListener was triggered!
What am I doing wrong? Why my BeforeAfterExecutionListener impl was not loaded and triggered?
P.S. All of the above code was executed under Intellij Idea 2021.1.3 Ultimate Edition
java version "1.8.0_341"
Java(TM) SE Runtime Environment (build 1.8.0_341-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)
here is intelliJs command:
C:\Tools\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:61280,suspend=y,server=n -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\groovyHotSwap\gragent.jar -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath C:\Users\userName\AppData\Local\Temp\classpath1705687115.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.testdirectly.application.testcase.TSuite_20
Which results in JUnit5IdeaTestRunner
My gradle dependencies
dependencies {
//JUnit platform
// to group tests by package, by class name, by class name pattern, etc (use #Suite, #SelectClasses) :junit-platform-suite-api:1.9.2
// and to filter/discover and run them (SuiteLauncher, SuiteTestEngine, SuiteTestDescriptor) :junit-suite-engine:1.9.2
testImplementation "org.junit.platform:junit-platform-suite:1.9.2"
//Launcher, engine discovery
testImplementation "org.junit.platform:junit-platform-launcher:1.9.2"//to run tests
//JUnit Jupiter
//to use assertions and so on
testImplementation "org.junit.jupiter:junit-jupiter-api:5.9.2"
//to use #ParameterizedTest
testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.2"
//Jupiter engine to run junit5 tests (JupiterTestEngine, Extensions, etc)
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.9.2"
}
Short answer
Option 5 works if you tweak it slightly (see below).
Long answer
Options 1 and 2 do not work because #ExtendWith is a Jupiter extension mechanism whereas #Suite triggers an engine of its own.
Test engines do not combine on the JUnit platform.
The same goes for option 4 since #BeforeAll and #AfterAll are Jupiter annotations.
Making Option 5 Work
First of all I'd suggest to use TestExecutionListener instead of LauncherSessionListener because the latter is still experimental.
Thus we have
package my.project.suites;
import org.junit.platform.launcher.*;
public class BeforeAfterSuiteListener implements TestExecutionListener {
#Override
public void testPlanExecutionStarted(TestPlan testPlan) {
System.out.println("before all");
}
#Override
public void testPlanExecutionFinished(TestPlan testPlan) {
System.out.println("after all");
}
}
The missing thing is now that you'll have to register BeforeAfterSuiteListener globally.
In classpath-based Java you do that through a resource file
META-INF/services/org.junit.platform.launcher.TestExecutionListener:
my.project.suites.BeforeAfterSuiteListener
Now before all and after all should show up in your output exactly once per test run.

Cannot read properties when used MockWebServer

Hi I am new to the Junit Testing and am trying to test the third party call, for that I have used MockWebServer from okhttp3, the mockWebServer does the job of giving me a proper mocked response but in the class that I am trying to test has the following
#Autowired
Environment env
....
...
..
String url = env.getProperty(shop.url);
The above is significant as it gets the url from application.yml
But the env is null whenever I am running that particular test method which uses MockWebServer
Main Class
Class ConnectionService {
#Autowired
Environment environment;
public ConnectionService(WebClient.Builder builder) {
this.webClient = builder.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.baseUrl(usersBaseUrl).build();
}
public void getShops(){
...
..
String url = env.getProperty(shop.url);
..
..
}
Test Class
#ExtendWith(SpringExtension.class)
#SpringBootTest
#AutoConfigureWireMock(port = 0)
class ConnectionServiceTest {
public static MockWebServer mockWebServer;
private static ConnectionService connectionService;
#BeforeAll
public static void setUp() throws IOException {
mockWebServer = new MockWebServer();
connectionService = new ConnectionService(WebClient.builder(),
mockWebServer.url("/").toString();
}
#AfterAll
static void tearDown() throws IOException {
mockWebServer.shutdown();
}
#Test
void testMethod() {
MockResponse mockResponse = new MockResponse()
.addHeader("Content-Type", "application/json; charset=utf-8")
.setBody("{\"status\":\"up\",\"details\":\"details\"}")
.throttleBody(16, 5, TimeUnit.SECONDS);
mockWebServer.enqueue(mockResponse);
connectionService.getShops();
}
}
Could someone please help me out figure what am I doing wrong, is it the MockWebServer that is causing environment to be null ? even the other properties in other files are null. Thanks in advance :)
I tried to test the WebClient by making use of MockWebServer, although it worked but now I cannot read any properties either from application.yml or otherProperties.properties as the environments variables are not getting injected

Testng how to get all the log steps in aftermethod for post issue on some bug tracking tools

I am working on a project where if test case is failed I have to post a bug on their bug tracking tools through the tools. But they want in a bug report all the steps should mentioned properly with error.
Like in the description they want like this
Open Url
List item
Click the submit button Dashboard title is not match properly
In My automation code, I have written log
public class logtest {
WebDriver driver;
#BeforeMethod
public void Before(){
driver=new ChromeDriver();
}
#Test
public void test1(){
Log.info("Open URl");
//Opened url
Log.info("Click on the submit button");
// Submit button Clicked
Log.info("Open Dashboard");
Log.info("Dashboard Title match");
}
#AfterMethod
public void AfterMethod(ITestResult result){
if (result.getStatus() == ITestResult.FAILURE) {
PostIssue_to_Somewhere();
}
}
}
Is there any want I can get all the steps that I print inside #Test in the after method
so I can post bugs to their board through API
I think I can save the result somewhere and print it the end of the test case but I don't think it's an ideal solution. If you have any suggestion or way that I can manage it using testing that will really helpful
You cannot get the result in after test method. you should use TestNG listener for get the results
Steps to get them :
First create your own class with extend listener class
public class Listener implements ITestListener
Then use the override method to get the results
#Override
public void onTestSuccess(ITestResult iTestResult) {
}
there are several method to get the exact data,
OnStart- OnStart method is called when any Test starts.
onTestSuccess- onTestSuccess method is called on the success of any test
onTestFailure- onTestFailure method is called on the failureof any Test.
onTestSkipped- onTestSkipped method is called on
skipped of any Test
onTestFailedButWithinSuccessPercentage- method
is called each time Test fails but is within success percentage.
onFinish- onFinish method is called after all Tests are executed.
Use Extent Report and then use its method like (log, pass, fail ) to log your steps in your report, based on your test result, if you still need help let me know :)
You can see the full project demo code at ( below is code for the extent report) https://github.com/0kakarot0/ExtentReportBasic.git
public class MyExtentReport {
private WebDriver driver;
ExtentSparkReporter spark;
ExtentReports extentReports;
ExtentTest extentTest;
public MyExtentReport(WebDriver driver) {
this.driver = driver;
}
//Created Extent Report Html File
public void extentReporter() {
Date date = new Date();
String rightNow = "Spark"+ date.getTime() + ".html" ;
String pathOfFile = "allReports/"+rightNow;
spark = new ExtentSparkReporter(pathOfFile);
extentReports = new ExtentReports();
extentReports.attachReporter(spark);
}
public void logTestNameAndDescription(String name, String description){
extentTest = extentReports.createTest(name, description);
}
public void logTestInfo(String testInfo){
extentTest.log(Status.INFO,testInfo);
}
public void logPassedTestSteps(String logPassMessage){
extentTest.pass(logPassMessage);
}
public void logFailTestSteps(String logFailMessage){
extentTest.fail(logFailMessage);
}
public void logFailTestScreenShot(String reasonOfFailure){
extentTest.fail(reasonOfFailure,MediaEntityBuilder.createScreenCaptureFromPath("utils/failedTestScreenShot/screenshot.png").build());
}
public void flushExtentReport(){
extentReports.flush();
}

JUnit to retrieve value from database to test criteria

How do I write JUnit with actual service/repository call to retrieve data from a database table instead of using a mock service/repository?
Here the below code returns an empty list of object, whereas I am expecting few hundred objects. findAll() is a simple method for which I am trying to write JUnit but later on I will be writing JUnit for a method which takes Map as JSON from request parameters and forms a criteria API so in this case, I would like to test
Request
Parsing of the request in Controller(what controller receives)
And forming the SQL Criteria and returned object and that's the reason I don't want to mock service/repository.
I am using Spring Boot Rest Controller and for Unit Testing, I am using Mocikito and JUnit.
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#WebMvcTest(CaDetailController.class)
public class CaDetailControllerTest {
private static ObjectMapper objectMapper = null;
private List<CaDetail> caDetails;
#Autowired
private MockMvc controller;
#MockBean
CaDetailRepository repository;
#BeforeClass
public static void beforeClass() {
objectMapper = new ObjectMapper();
}
#Before
public void before() {
caDetails = new ArrayList<CaDetail>();
}
#After
public void after() {
caDetails = new ArrayList<CaDetail>();
}
#AfterClass
public static void afterClass() {
objectMapper = null;
}
#Test
public void getCorporateActions() throws Exception {
MvcResult result = controller.perform(MockMvcRequestBuilders.get("/api/ca").accept(MediaType.APPLICATION_JSON)).andReturn();
caDetails = objectMapper.readValue(result.getResponse().getContentAsByteArray(), new TypeReference<List<CaDetail>>() {
});
System.out.println(">>>>>>>>>>>>>>> caDetails : " + caDetails);
assertNotNull(caDetails);
assertTrue(caDetails.size() > 0);
}
You need to write integration test for your services which will directly communicate with database. For example go through this link.
http://www.springboottutorial.com/integration-testing-for-spring-boot-rest-services

Spring Data neo4j JUnit4 setup

I confess I am a total newbie at the Java way of doing things and I am totally lost trying to get a simple unit test running.
I am building a data access library and want to unit test it. I am using Spring Data Neo4j 4.0.0.BUILD-SNAPSHOT because I need to connect to a remote Neo4j server in the real world.
After battling errors all day I am at the point where I have a test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = {"org.mystuff.data"})
#ContextConfiguration(classes={Neo4jTestConfiguration.class})
public class PersonRepositoryTest {
#Autowired
PersonRepository personRepository;
protected GraphDatabaseService graphDb;
#Before
public void setUp() throws Exception {
graphDb = new TestGraphDatabaseFactory().newImpermanentDatabase();
}
#After
public void tearDown() {
graphDb.shutdown();
}
#Test
public void testCreatePerson() throws Exception {
assertNotNull(personRepository);
Person p = new Person("Test", "User");
personRepository.save(p);
}
}
Neo4jTestConfiguration.java
#Configuration
#EnableNeo4jRepositories(basePackages = "org.mystuff.data")
#EnableTransactionManagement
public class Neo4jTestConfiguration extends Neo4jConfiguration {
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory("org.mystuff.data");
}
#Bean
public Neo4jServer neo4jServer() {
// What to return here? I want in-memory database
return null;
}
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}
When running tests the personRepository.save() throws and exception 'No Scope registered for scope "session"'
I don't know if I need the configuration class but my test class won't work without it because Spring needs #ContextConfiguration and I want all the DI niceness Spring provides (amongst other things).
How can I get my tests to work with Spring?
You can use an InProcessServer which is an in-memory database:
#Bean
public Neo4jServer neo4jServer() {
return new InProcessServer();
}
Omit the session scope as your test isn't running in a web container. An example: https://github.com/neo4j-examples/sdn4-cineasts/blob/4.0-RC1/src/test/java/org/neo4j/cineasts/PersistenceContext.java
This will require dependencies as described in this question: Spring Data Neo4j 4.0.0.M1 Test Configuration
In your test class PersonRepositoryTest, you don't need to construct an instance of the database, your tests will run against the same InProcessServer.
Here's an example: https://github.com/neo4j-examples/sdn4-cineasts/blob/4.0-RC1/src/test/java/org/neo4j/cineasts/domain/DomainTest.java