How to conditionalize GUI tests using Netbeans/Maven vs maven on command line invocation - maven-2

I'd like to have a single project pom but have my GUI tests always run when I'm invoking JUnit on Netbeans, but have them conditional (on an environment variable?) when building on the command line (usually for production build - on a headless machine, but sometimes just for build speed).
I don't mind instrumenting my JUnit tests for this, as I already have to set up my GUI test infrastructure, but how do I conditionalize my pom!
Netbeans 6.5 with Maven plugin.
Any ideas how I can accomplish this?
Ilane

The Surefire plugin can specify which tests to run.
You could specify different sets to run for different profiles, and select your profile using -P{profilename}.

One solution would be to use a profile (that could be indeed activated by an environment variable) and to exclude GUI tests from the Maven Surefire Plugin configuration using excludes in this profile, based on a naming convention. Something like this:
<profile>
<id>headless</id>
<activation>
<property>
<name>env.FOO</name>
<value>foo</value>
</property>
</activation>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<excludes>
<exclude>**/*$*</exclude><!-- to exclude inner classes -->
<exclude>**/gui/**</exclude>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
</profile>
Another option would be to use TestNG and to leverage the excludeGroups parameter.

To achieve the desired behavior in my Maven project on Netbeans, I set up a profile defining an environment variable in my project's pom and modified the Test file action in my project's properties to activate my new profile. In this way I could check the enviroment variable in my tests. (This could have been done similarly with a system property.)
To keep from having to add a check to each and every GUI test, however, I found that I could add a JUnit filter, which would automatically ignore the UI tests in the case where I didn't want to run them and put the number of skipped tests in the test result line.
Here what my profile looks like:
<profile>
<id>test-gui</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>false</skipTests>
<excludes>
<exclude>**/TestSuite.java</exclude>
</excludes>
<environmentVariables>
<GUI_TEST>true</GUI_TEST>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Here's a description of how to update the Netbeans Action:
(Right click on project in Projects window)->Properies
In Categories box, select 'Actions'
In Actions box, select 'Test file'
In Activate Profiles textfield, enter 'test-gui'
Click 'OK' button to save.
To add the JUnit filter (and the documentation was sparse, so I may not have done this in the most effective manner), I subclassed the default test runner, TestClassRunner and had it call my Filter, which checks the test name and the environment variable. To get JUnit to call my class, I annotated the test class.
public class GUITestClassRunner extends TestClassRunner {
public GUITestClassRunner(Class klazz) throws InitializationError {
super(klazz);
}
public GUITestClassRunner(Class klazz, Runner runner)
throws InitializationError, NoTestsRemainException {
super(klazz, runner);
}
#Override
public void run(RunNotifier notifier) {
if (getDescription().testCount() > 0) {
try {
filter(new GUIFilter(notifier));
} catch (NoTestsRemainException ex) {
Description description = getDescription();
notifier.fireTestStarted(description);
notifier.fireTestIgnored(description);
notifier.fireTestFinished(description);
return;
}
}
super.run(notifier);
}
class GUIFilter extends Filter {
private boolean isGUI = false;
private RunNotifier notifier;
public GUIFilter(RunNotifier notifier) {
this.notifier = notifier;
isGUI = UI.isGUITestEnvironment();
}
#Override
public boolean shouldRun(Description desc) {
if (!isGUI && UI.isGUITest(desc.getDisplayName())) {
Description description = getDescription();
notifier.fireTestStarted(description);
notifier.fireTestIgnored(description);
notifier.fireTestFinished(description);
return false;
}
return true;
}
#Override
public String describe() {
return "all tests except GUI tests if headless";
}
}
}
To call this runner, the test class needs to be annotated with:
#RunWith(GUITestClassRunner.class)
public class MyJUnitTestClass
{
....
#Test
public void testAlpha() {...}
#Test
public void testBeta_UI() {...}
}
So, now, from Netbeans, I just run my unit test class and the GUI tests automatically run. I can run from the command line with no environment variables set or GUI_TEST set to false, and my GUI tests are skipped, or I can run from the command line with GUI_TEST set to true, or use mvn -Ptest-gui and all my GUI tests run.
My sincerest thanks to Brian and Pascal for pointing me in the right direction.
Ilane

Related

Log custom text to Cucumber JVM or Extent Reports

Please guide me in logging custom text which are there inside a method into Cucumber JVM (Masterthought) or Extent Reports.
I am using Cucumber Junit BDD Framework and have the below dependencies in my POM file -
<!-- Cucumber JVM Report -->
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>5.1.0</version>
</dependency>
<!-- Extent Report -->
<dependency>
<groupId>com.aventstack</groupId>
<artifactId>extentreports-cucumber4-adapter</artifactId>
<version>1.2.1</version>
</dependency>
And my Runner file is as below -
#CucumberOptions(
tags = {"#SANITY,#REGRESSION,#E2E"},
features = "src/test/resources/cta-features/features/",
plugin = {
"json:target/cucumber-reports/cucumber.json", "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:",
"pretty"
},
glue = {
"e2e.steps",
"e2e.hooks"
})
#RunWith(Cucumber.class)
public class TestRunner {
#BeforeClass
public static void init() throws Exception {
}
#AfterClass
public static void generateReport() throws Exception {
File reportOutputDirectory = new File("target");
List<String> jsonFiles = new ArrayList<>();
jsonFiles.add("target/cucumber-reports/cucumber.json");
String buildNumber = "1";
String projectName = "Project";
Configuration configuration = new Configuration(reportOutputDirectory, projectName);
// optional configuration - check javadoc for details
configuration.addPresentationModes(PresentationMode.RUN_WITH_JENKINS);
// do not make scenario failed when step has status SKIPPED
configuration.setNotFailingStatuses(Collections.singleton(Status.SKIPPED));
configuration.setBuildNumber(buildNumber);
// addidtional metadata presented on main page
configuration.addClassifications("Platform", "Windows");
configuration.addClassifications("Browser", "Chrome");
configuration.addClassifications("Branch", "release/1.0");
ReportBuilder reportBuilder = new ReportBuilder(jsonFiles, configuration);
Reportable result = reportBuilder.generateReports();
// and here validate 'result' to decide what to do if report has failed
}
I am able to successfully generate report in both master thought and Extent which will contain Feature level statements and Step Level statements (I have used scenario.write for this). But my client wants one more level deeper where he can get info as to which link or button was clicked etc which i am currently publishing to my console using Log4j
Example :
Log.info("Random Button or Link was clicked and Operation is successful")
My clients wants this to be integrated into the report (In Either Masterthought or Extent). Is there a way to do this ?
Extent cucumber adapter provides addtestlog to log additional steps .
Please check below example -
ExtentCucumberAdapter.addAddTestStepLog(BTN.getText());
As per your Pom.xml file you are using adapter 4 if you cannot find method try to switch into cucumber adapter 6 and other essential dependency of cucumber 6. That will surely help you :)

How to make synchronized work when using maven-surefire plugin?

I'm using the maven-surefire plugin to execute the Cucumber Runner in parallel. In each of the Runners, I'm invoking a synchronized static method of a Utilities class. But all the Runners running in parallel are able to invoke the method in a non-synchronized way.
#RunWith(CucumberWithSerenity.class)
#CucumberOptions(...)
public class SampleRunner {
#BeforeClass
public static void loadLocators() {
Utilities.doSomething();
}
}
public class Utilities {
public synchronized static void doSomething() {
System.out.println("Start");
.
.
.
System.out.println("Stop");
}
}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<includes>
<include>**/*Runner.java</include>
</includes>
<parallel>classes</parallel>
<threadCount>${parallel.tests}</threadCount>
<forkCount>${parallel.tests}</forkCount>
<perCoreThreadCount>true</perCoreThreadCount>
<!-- <skip>true</skip> -->
</configuration>
</plugin>
And when I have the threadCount as say 3, and execute mvn clean verify serenity:aggregate
I get the following logs
Start
Start
Stop
Stop
Start
Stop
What I am Expecting is
Start
Stop
Start
Stop
Start
Stop
Set the forkCount to 1 and only 1 JVM will be used by the plugin to execute the tests. If more than 1 then multiple JVMs will be used and hence different synchronized static method will be used.
Reference: https://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html

Migrating from Selenium RC to Webdriver

I'm trying to migrate to webdriver, as it is faster. How do I do this?
Currently I'm using the setUp() command for selenium. Do I need to add any new jar files for the webdriver?
I 'd like to describe in common features approach I use on my project.
I'm using selenium webDriver. Working on java.
IDE: IDEA.
build manager: maven.
So I got POM.xml file.
So I simply add there depencdencies in POM xml:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
<dependency> <groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.24.1</version>
</dependency>
On building the project maven will get needed jars automatically.
In my project I got BaseSeleniumTest.java: with the following:
public class BaseSeleniumTest extends SeleneseTestBase {
static WebDriver driver;
#BeforeClass
public static void firefoxSetUp() throws MalformedURLException {
driver = new FirefoxDriver();
}
#Before
public void homePageRefresh() throws IOException {
driver.get("login.base.url");
}
#AfterClass
public static void closeFirefox(){
driver.quit();
}
...
}
And have some other classes inherinting from BaseSekeniumTest.java
where I describe pack of my selenium tests annotated by #Test
That's kind of structure on my project.
Hope this helps you.

Custom Eclipse plugin deployment with popup contribution to Package Explorer

I have developed a simple plugin to generate some routine code. This plugin has a contribution to a popup menu of Package Explorer. It is working as intended when running from the development environment (Launch as Eclipse application from Eclipse RCP) -- an appropriate menu item appears in the menu, and its invocation does what is expected.
However, I'm having a hard time deploying it into a different Eclipse instance.
The developed plugin was exported with Export Wizard, which produced a separate jar file. This jar file has been placed into the dropings directory of another Eclipse installation (newly unpackaged). When this Eclipse instance launches, the popup menu of Package Explorer does not contain the contributed menu item. The information from Eclipse Installation Details shows that the plugin is present on the Plug-Ins tab, and the Configuration tab has it listed as tg.companion (1.0.0.201208132302) "Companion Object Generator" [Starting].
What am I missing? Why the contributed menu item does not show up?
Thanx.
The locationURI for the menu contribution is popup:org.eclipse.jdt.ui.PackageExplorer, the value for property allPopups is true.
The plugin is unsigned.
Here's the plugin files that might shed some light.
Plugin.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension point="org.eclipse.ui.menus">
<menuContribution
allPopups="true"
locationURI="popup:org.eclipse.jdt.ui.PackageExplorer">
<command
commandId="tg.companion.handler.generator"
label="TG Create Companion Object"
style="push"
tooltip="Creates a companion object to the selected entity object, and provides DAO/RAO implementations">
</command>
</menuContribution>
</extension>
<extension point="org.eclipse.ui.commands">
<command
defaultHandler="tg.companion.handler.GenerateCompanionObjects"
id="tg.companion.handler.generator"
name="Generate Comanion">
</command>
</extension>
</plugin>
MANIFEST.MF:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Companion Object Generator
Bundle-SymbolicName: tg.companion;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: tg.companion.Activator
Bundle-Vendor: TG
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.jdt.core;bundle-version="3.8.1",
org.eclipse.core.resources;bundle-version="3.8.0",
org.eclipse.core.expressions;bundle-version="3.4.400"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Command handler:
package tg.companion.handler;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.handlers.HandlerUtil;
public class GenerateCompanionObjects extends AbstractHandler implements IHandler {
#Override
public Object execute(final ExecutionEvent event) throws ExecutionException {
final Shell shell = HandlerUtil.getActiveShell(event);
final ISelection sel = HandlerUtil.getActiveMenuSelection(event);
final IStructuredSelection selection = (IStructuredSelection) sel;
final Object firstElement = selection.getFirstElement();
if (firstElement instanceof ICompilationUnit) {
createOutput(shell, (ICompilationUnit) firstElement);
} else {
MessageDialog.openWarning(shell, "Companion Object Generation Warning", "Please select an entity object for generating a corresponding companion.");
}
return null;
}
private void createOutput(final Shell shell, final ICompilationUnit cu) {
// does code generation work using Java Model
}
}
Finally, the problem has been solved!
After careful review of the project structure it was identified that build.properties file (for some reason) did not have plugin.xml checked. As the result, plugin.xml was not included into the produced by the export wizard jar file.
Once the build.properties files has been amended to include plugin.xml, the resulting jar file had it included and deployed without any issues.
Interestingly, the plugin export wizard did not even warn about the exclusion of plugin.xml, which I would personally have expected.

How to start and stop mule in maven

I need to start Mule before I run my tests, and stop it when the tests are finished. It is unclear to me how to alter my Maven pom to accomplish this. So far I have the following in my pom:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>org.mule.MuleServer</argument>
<argument>-config</argument>
<argument>my-config.xml</argument>
</arguments>
</configuration>
</plugin>
--- Update ---
After some replies below I decided to add some additional details.
I have several unit tests extending Mules FunctionalTestCase class:
public class SomeUnitTest extends FunctionalTestCase
I started writing some new customer acceptance tests using JBehave which are wired to run during mavens "integration-test" phase. These tests cannot succeed without an instance of mule running. The main class that loads and executes the stories already extends the JUnitStories class:
public class MyStories extends JUnitStories
Since I cannot inherit from FunctionalTestCase in this class, I need to look at alternatives to getting mule to run and stop when I need it for these stories.
Why don't you use Mule's FunctionalTestCase instead? It fires up an in-memory Mule and loads up your configs. Not sure what you gain from starting the whole standalone Mule.
You could probably accomplish what you want by leveraging maven's phases. You'd have to define 2 executions. One to start mule and one to stop it. You'd start mule in one of the pre-test phases (maybe something like process-test-classes) and then stat mule after the test phase. It could be pretty tricky, though.
Another possibility is to fire mule up in junit, somewhere like in a BeforeClass setup function. This will probably be much easier. See:
http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html
class muleDriver {
#BeforeClass
public static startMule() {
....programmatically initialize Mule....
....You should be able to grab the config files from the classpath....
}
#Test
public void testSomething() {
....Run Some Tests...
}
}
The other question I'd ask is why you'd want to fire up the whole mule framework for tests. I was on a team that did this, and tests ended up taking a tremendous amount of time during builds because they were firing up mule many times throughout the testing cycle (and other teams copied the pattern.)
Try using junit #ClassRule. The side effect is that individual test cases can not be executed any more.
#RunWith(Suite.class)
#Suite.SuiteClasses({MuleFlowTest.class})
public class MuleSuite {
#ClassRule
public static ExternalResource testRule = new ExternalResource() {
#Override
protected void before() throws Throwable {
final String CLI_OPTIONS[] = {"-config", FlowTestUtil.getURI() };
MuleServer server = new MuleServer(CLI_OPTIONS);
server.start(false, true);
mc = server.getMuleContext();
muleServer = server;
};
#Override
protected void after() {
System.out.println("Shutdown");
muleServer.shutdown();
muleServer = null;
}
};
private static MuleServer muleServer;
public static MuleContext mc;
}
public class MuleFlowTest {
#Test
public void flowTest() {
assertNotNull(MuleSuite.mc);
}
}