How to get runtime values through (Maven, TestNG, Java) - java

I am just started to automate my Web service project with Java. I need to run it in Jenkins so I built the project with TestNG framework and Maven. I am able to run some automated test suite with Jenkins without any issues.
Now I have problem like, I need to get the user input at runtime (say HostName, UserName, Password, etc) and then the test suite should run accordingly.
The problem I am facing like, while entering the input in the console the cursor is not returning back to the program and it simple going to ideal state.
PFA screenshots:
Test case running as Maven build
Test case running as TestNG

Making your tests interactive is absolutely bad approach - the build is just not reproducible at all, makes other people know what parameters are expected and so on.
If your test case need to take parameters at runtime (or more accurately, they need to be set before maven build is started) you have several options.
Option #1. Properties file and maven resource processing.
Idea is just to have a properties file in your project and tell maven to resolve variable
values there. Example:
Pom.xml:
<resources>
<resource>
<directory>src/test/resources/data</directory>
<filtering>true</filtering>
</resource>
</resources>
/src/test/resources/data/myproperties.properties:
myVar = ${myVar}
Then run maven build as:
mvn -DmyVar=value clean install
You can use not only properties files, but any other file types (for example XML).
Hint: you can use maven-enforcer-plugin to force user to enter -DmyVar, this plugin will fail the build if all required properties are not set.
Option #2. Properties file and Spring DI.
Idea is almost same as above, but Spring is used to inject all necessary stuff to test class. Something like:
#Component
public class MyTest
{
#Value(${myProperty})
private String myValue;
// ... Test methods which can use myValue ...
}
See this answer for full example of possible Spring configuration.
Btw, your test is the a unit test, but integration test - in case if it involves deploying of your web service or something else like this. Therefore, it would be wise to split unit tests (maven-surefire-plugin) and integration tests (maven-failsafe-plugin).

Related

Any way to create a permanent JUnit config. on IntelliJ?

I try to test my spring boot application via JUnit 5.
The test methods need some environment variables. Even I put them on the list, each test method creates a new JUnit config so I have to put them again.
I saw the document on JetBrains.
I can not save the JUnit config. because each config. depends on the method.
Is there any way to create a permanent JUnit config. on IntelliJ?
You may edit the Junit run configuration in the "Run configuration templates for new projects":
This is a bad idea. Setting up your environment variables in something like IntelliJ will make this unportable or unrunnable in a Jenkins environment.
Because you're using Spring Boot, you have more flexibility than you realize. Rework your code so that the environment variables can be injected in through application properties. Then, you can add the application properties to your test through the #SpringBootTest annotation.

How to edit app.properties file with build parameter in Jenkins

I have a selenium script which I want to run from Jenkins. I have a properties file called app.properties. This file consists properties such as:
browser=chrome
I configured my project as parameterized so when I run my build, it asks for browser parameter. I want to select this parameter(for example firefox), so that it will change browser property in app.properties and will run the automation in Firefox.
Normally, when I change the browser property in app.properties in Intellij, my program runs with that browser. So there is nothing wrong with my program in that sense.
Is there a way to change app.properties with respect to my Jenkins build parameter and run the program with that configuration?
EDIT: I found the following solution:
Install surefire plugin.
Add a browser parameter.
In your property managing class, take browser parameter as
System.getProperty("browser");
From jenkins, configure a browser parameter
Invoke maven command: mvn test "-Dbrowser=${BROWSER}"
You can pass system properties to change configuration.
First you should configure your project to read both system properties and configuration file, where system properties will have higher priority. I'd recommend Apache Commons Composite Configuration. It can look like this:
CompositeConfiguration configuration = new CompositeConfiguration();
try {
configuration.addConfiguration(new SystemConfiguration());
configuration.addConfiguration(new PropertiesConfiguration("app.properties"));
} catch (ConfigurationException e) {
e.printStackTrace();
}
//Read your configuration values here
This way when you provide system property -Dbrowser=chrome it will override value from configuration file.
Secondly, you'll need to configure Jenkins job. Since you're passing a parameter you can use it in your build step definition:
mvn clean test -Dbroswer=${browser-param}
“The way parameters take effect is also different depending on the parameter type you choose ... String parameters are exposed as environment variables of the same name.”
https://wiki.jenkins.io/plugins/servlet/mobile?contentId=34930782#content/view/34930782

Jacoco plugin does not report coverage for renamed integration test class

Let me show you the problem with the following use case:
Let's assume I have class Example and want to use the unit and integration test for that.
Once the unit tests in file ExampleTest (with methods annotated by #Test) is done, coverage report displays correct result.
Once the integration tests in file ExampleTestInt (with methods annotated by #Test) is done, coverage report does not display correct result. As if the class was excluded from the coverage process.
That means if I have just integration tests for Example class then I cannot see the correct result in coverage by jacoco.
Is there some way how to keep that ExampleTestInt class to be coverage similarly like in case of the unit test? I would like to keep the same name.
You can configure custom excludes like this:
<configuration>
<excludes>
<exclude>**/*Config.*</exclude>
<exclude>**/*Dev.*</exclude>
</excludes>
</configuration>
Please checkout the jacoco docs: https://www.eclemma.org/jacoco/trunk/doc/report-mojo.html
I have found out that the root problem was in wrong filename used for integration tests.
As per my observation the jacoco coverage plugin was looking for files with suffix Test and hence the file ExampleTestInt couldn't be seen by plugin.

Setting system property get agent in teamcity maven build

I am trying to create plugin, which deploys my application in pre-integration-phase and runs the test against it. Now my application requires some property called LOOKUPLOCATOR which should be unique per envrionment. Now i have multiple agents configured in teamcity and many builds can run in parallel and if all the builds will have same property they will interfere with each other and test results will be unexpected.
Is there a way so that when my build run and in my java code if somehow get to know the agent name, and i will maintain a hardcoded value for LOOKUPLOCATOR for each agent, we can set that value. So my property will be per agent
Teamcity has some pre-defined variables which are available while a build is running. Agent name can be found in %teamcity.agent.name%.
Here is how to set agent-specific parameters
If additional applications/libraries are available in the environment, the administrator can manually define the property in the /conf/buildAgent.properties file. These properties can be used for setting various build configuration options, for defining build configuration requirements (for example, existence or absence of some property) and inside build scripts.

Setting OSGi storage directoy (org.osgi.framework.storage) does not work in Maven triggered JUnit test

In my code I start multiple OSGi frameworks using EquinoxFactory. By setting the property "org.osgi.framework.storage" to "#user.home/osgi-frameworks/framework-x", where x is different for every framework, each framework uses a different directory:
frameworkProperties.put("osgi.clean", "true");
frameworkProperties.put("osgi.console", "true");
frameworkProperties.put("org.osgi.framework.storage",
"#user.home/osgi-frameworks/osgi-framework-"
+ numberOfFramework);
framework = new EquinoxFactory().newFramework(frameworkProperties)
This works perfectly when running the actual application. Also the JUnit tests in the IDE run without any problems.
However, when I start the Maven build for my project, the JUnit tests fail since all frameworks use the same directory ("osgi-frameworks/framework-0").
I added logging to the application to check whether the property "org.osgi.framework.storage" does really have different value in the OSGi property map. Everything looks fine in the log, but when checking the file space, only one directory has been created.
Since I would like to include the application in Jenkins, I would rather not skip the tests.
Has anyone an idea what could be wrong? Do I have to set other parameters for the framework? Is there any considerable difference between Junit in the IDE and in Maven?

Categories