I'm trying to implement org.testng IReporter Interface. My Java is not that great, base on some example I found online I was able to create a Reporter class. The problem I'm having is how to use it and where do I call it and how and which parameters to pass to it?
public class Reporter implements IReporter {
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory){
ISuiteResult results =suites.get(0).getResults().get("Sanity Suite");
ITestContext context = results.getTestContext();
IResultMap passedTests = context.getPassedTests();
IResultMap failedTests = context.getFailedTests();
// Print all test exceptions...
for( ITestResult r: failedTests.getAllResults()) {
System.out.println( r.getThrowable());
}
}
}
For example I have this WebDriver Selenium TestNG test:
public class VerifyTest extends TestBase {
#Test
public void test1() {
verifyTrue(false);
verifyEquals("pass", "fail");
verifyFalse(true);
}
#Test
public void test2() {
verifyTrue(false);
assertEquals("pass", "fail");
verifyFalse(true);
}
How would I use my Reporter to get a customize report at the end of the run???
Thank You!
Just expand your skeleton above to generate your results where you want them, .xml, .html, text file, etc...
David, you can add your custom reporter to your testng.xml in case you are invoking your tests through an xml in the suite section.
<listeners>
<listener class-name="yourpackage.Reporter"/> </listeners>
In case you are programmatically invoking those, then you need to add it through your code as documented # Running TestNG programmatically
If you are invoking your tests from command line, refer this
This reporter would be invoked by TestNG at then end of all the runs, if you specify in either of the above ways.
I created a project that is an example of generating a customized report.
The basic idea is to create a Listener class and reference it in the testing.xml file.
<listeners>
<listener class-name="qa.hs.framework.CustomReportListener"/>
</listeners>
And then create the class:
public class CustomReportListener implements IReporter {
#Override
public void generateReport( List<XmlSuite> xmlSuites, List<ISuite> suites,
String outputDirectory ) {
System.out.println();
//Iterating over each suite included in the test
for (ISuite suite : suites) {
//Following code gets the suite name
String suiteName = suite.getName();
//Getting the results for the said suite
Map<String, ISuiteResult> suiteResults = suite.getResults();
for ( ISuiteResult sr : suiteResults.values() ) {
ITestContext tc = sr.getTestContext();
System.out.println("Passed tests for suite '" + suiteName + "' is:" +
tc.getPassedTests().getAllResults().size());
}
CustomReport cr = new CustomReport();
cr.generateReport( xmlSuites, suites, outputDirectory );
...
Then, from that Listener class you can create a "Report Writer" class that creates any arbitrary HTML output using something like so:
public class CustomReport extends CustomReportListener
{
private static final Logger LOG = Logger.getLogger( CustomReport.class );
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat(" MMM d 'at' hh:mm a");
private String reportFileName = Constants.reportFileName;
private PrintWriter m_out;
private int m_row;
private Integer m_testIndex;
private int m_methodIndex;
private Scanner scanner;
#Override
public void generateReport( List<XmlSuite> xml, List<ISuite> suites, String outdir ) {
try {
m_out = createWriter( outdir );
}
catch ( IOException e ) {
LOG.error("output file", e);
return;
}
startHtml(m_out);
generateSuiteSummaryReport(suites);
generateMethodSummaryReport(suites);
generateMethodDetailReport(suites);
endHtml(m_out);
m_out.flush();
m_out.close();
}
And finally, from that "CustomReport" class your "generate report" methods all have access to all data from the report, such as:
testContext.getPassedTests()
Map<String, ISuiteResult> r = suite.getResults()
method.getDescription()
method.getTestClass().getName()
ITestResult.SUCCESS
tests.getAllMethods()
overview.getStartDate().getTime()
overview.getIncludedGroups()
etc.
You can use
#Listeners(ReporterClassName.class)
ex:
#Listeners(Reporter.class)
public class VerifyTest extends TestBase
Beautiful reporting with realtime report of any running test is possible using RealTime report plugin. Very easy to use and no modification needed in existing code, for details please visit this github url RealTimeReport
You can find details implementation of different TestNg Reporting intrfaces
Related
Normally I would write a cucumber option as below:
#CucumberOptions(
features = "src\\main\\java\\feature"
, glue= "stepdefination",
plugin= {"com.cucumber.listener.ExtentCucumberFormatter:Report/Report.html"}
tags="#tag, #tag1, #sort"
)
public class TestRunner extends TestFunction {
#Test
public void runcukes( ) {
new TestNGCucumberRunner(getClass()).runCukes();
}
#BeforeClass
public void tags() {
}
#AfterClass
public void writeExtentReport() {
Reporter.loadXMLConfig("extent-config.xml");
}
}
My question is: How can I fetch #tag, #tag1, #sort from an excel file to #cucmberoptions and run the program in Selenium Java?
I am not sure about using cucumber options but by using cucumber RuntimeOptions class you can achieve it. The below method needs to be called in a loop that means you have 10 tags to execute then call this method in for loop.
public static boolean cucumberRun(String tag) {
try {
ClassLoader classLoader = CustomClass.class.getClassLoader();
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
/* Adding cucumber plugins */
List<String> pluginList = new ArrayList<String>();
pluginList.add("--plugin");
pluginList.add("html:target/cucumber-html-report");
pluginList.add("--plugin");
pluginList.add("json:target/cucumber.json");
pluginList.add("--plugin");
pluginList.add("com.cucumber.listener.ExtentCucumberFormatter:");
pluginList.add("--plugin");
pluginList.add("rerun:target/failedScenarios.txt");
/* Location for BDD extent report. */
ExtentProperties extentProperties = ExtentProperties.INSTANCE;
extentProperties.setReportPath("location/Extent_report.html");
/*
* Adding cucumberOptions.
*
* You can get the tag value from excel and pass it here. We need to add # before tag value.
*/
RuntimeOptions ro = new RuntimeOptions(pluginList);
ro.getFilters().add("#"+tag);
ro.getFeaturePaths().add("location of feature files");
ro.getGlue().add("location of glue code");
/* Loads all the resources into Cucumber RunTime class and execute. */
cucumber.runtime.Runtime runtime = new cucumber.runtime.Runtime(resourceLoader, classFinder, classLoader,
ro);
runtime.run();
}catch(Exception e){
// Handle exception
}
I want to log name of the test suite before running it. I succeed on logging method names but couldn't figure out how I can do the same thing with suites. My code:
EDIT: I found the solution. Here is the code for those who need it.
public class TestCase {
private Logger logger = LogManager.getLogger(this.getClass());
protected static WebDriver driver;
private String url = PropertyManager.getUrl();
private String browser = PropertyManager.getBrowser();
#BeforeSuite
protected void setUp(ITestContext tes) {
System.setProperty("webdriver.chrome.driver","chromedriver.exe");
System.setProperty("webdriver.chrome.logfile", "chromedriver.log");
System.setProperty("webdriver.chrome.verboseLogging", "true");
driver = new ChromeDriver();
driver.get(url);
driver.manage().window().maximize();
logger.info("Starting up {} driver.", browser);
logger.info(tes.getSuite().getName());
}
This can be done by adding Listener in the project. Use IInvokedMethodListener to perform activities before invocation of intended method.
Steps:
Create a class lets say ListenerClass and implement IInvokedMethodListener interface in it.
public class ListenerClass implements IInvokedMethodListener
Add all unimplemented method and add below code in beforeInvocation method :
#SuppressWarnings("deprecation")
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
try {
if (method.getTestMethod().getMethod().getAnnotation(org.testng.annotations.BeforeSuite.class)
.toString() != null) {
System.out.println("Before suite annoted method name - " + method.getTestMethod().getMethodName());
System.out.println("Test suite name - " + testResult.getTestContext().getSuite().getName());
}
} catch (Exception e) {
}
}
Add the listener class in your testng.xml file
<listeners>
<listener class-name="ListenerClass"></listener>
</listeners>
<test name="Test_Name">
<classes>
<class name="Test_Class_Name" />
</classes>
</test> <!-- Test -->
Run testng.xml as TestNGSuite you will get the expected result. Let me know if any thing is there
I have to execute test scripts using dynamic testng.xml file which means I have to create testng.xml file thru code and pass the parameters to the #Test methods pro grammatically.
For that I have created two Java files DynamicTestNG.java which should generate testng.xml file and run SampleClass.java where the #Test method has been written along with the parameters.
DynamicTestNG.java
public class DynamicTestNG {
public void runTestNGTest(Map<String,String> testngParams) {
//Create an instance on TestNG
TestNG myTestNG = new TestNG();
//Create an instance of XML Suite and assign a name for it.
XmlSuite mySuite = new XmlSuite();
mySuite.setName("MySuite");
//Create an instance of XmlTest and assign a name for it.
XmlTest myTest = new XmlTest(mySuite);
myTest.setName("MyTest");
//Add any parameters that you want to set to the Test.
myTest.setParameters(testngParams);
//Create a list which can contain the classes that you want to run.
List<XmlClass> myClasses = new ArrayList<XmlClass> ();
myClasses.add(new XmlClass("SampleClass"));
//Assign that to the XmlTest Object created earlier.
myTest.setXmlClasses(myClasses);
//Create a list of XmlTests and add the Xmltest you created earlier to it.
List<XmlTest> myTests = new ArrayList<XmlTest>();
myTests.add(myTest);
//add the list of tests to your Suite.
mySuite.setTests(myTests);
//Add the suite to the list of suites.
List<XmlSuite> mySuites = new ArrayList<XmlSuite>();
mySuites.add(mySuite);
//Set the list of Suites to the testNG object you created earlier.
myTestNG.setXmlSuites(mySuites);
TestListenerAdapter tla = new TestListenerAdapter();
myTestNG.addListener(tla);
//invoke run() - this will run your class.
myTestNG.run();
}
public static void main (String args[])
{
DynamicTestNG dt = new DynamicTestNG();
//This Map can hold your testng Parameters.
Map<String,String> testngParams = new HashMap<String,String> ();
testngParams.put("searchtext1", "testdata1");
testngParams.put("searchtext2", "testdata2");
dt.runTestNGTest(testngParams);
}
}
And SampleClass.java
public class SampleClass {
private WebDriver driver;
#BeforeTest
public void setUp()
{
System.setProperty("webdriver.chrome.driver","C:\\Users\\AK5040691\\Desktop\\IE driver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.navigate().to("http://executeautomation.com/blog/custom-testng-library-for-appium/#more-1562");
}
//#Parameters({"searchText1","searchText2"})
//#Test
public void searchText(String text1, String text2)
{
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text1);
driver.findElement(By.className("search-field")).clear();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text2);
}
}
Its not running. Please let me know the mistake here.
You have to uncomment the #Test annotation in your SampleClass file. And if your SampleClass is in a package , then absolute package name + class name is to be specified in this statement.
myClasses.add(new XmlClass("com.some.package.SampleClass"));
Generally TestNG classes have a suffix or prefix labelled "Test" so that surefire plugin can include them in the execution flow, in case if you are using maven.
You can instead use the constructor with parameter of class object .
myClasses.add(new XmlClass(SampleClass.class));
Does Jmeter supports Junit testsuite?
This question trouble me for several days, the test cases all working well no matter a style of junit 3 or 4. But the testsuite is anyway dumb.
Any suggestions?
My code below:
public class LoginLogout extends TestCase {
private static Logger log = Logger.getLogger(LoginLogout.class);
public static Test suite() {
try{
log.info("test suite start!");
TestSuite suite = new TestSuite(LoginLogout.class.getName());
//$JUnit-BEGIN$
suite.addTestSuite(Login.class);
suite.addTestSuite(Logout.class);
return new TestSetup(suite) {
protected void setUp(){
log.info("test suite setup!");
}
protected void tearDown(){
log.info("test suite finished!");
}
};
}catch(Exception e){
log.error(e.getMessage());
}
return null;
}
}
public class Login extends TestCase {
private static Logger log = Logger.getLogger(Login.class);
#Test
public void testLogin() throws Exception {
log.info("login start!");
log.info("login end!");
}
}
public class Logout extends TestCase {
private static Logger log = Logger.getLogger(Logout.class);
#Test
public void testLogout() throws Exception {
log.info("logout start!");
log.info("logout end!");
}
}
You can go to "Download Apache JMeter" page on http://jmeter.apache.org/ , and download the "apache-jmeter-2.8_src.zip" (or whatever the current version is).
After unzipping it, under apache-jmeter-2.8_src\apache-jmeter-2.8\src\junit\test directory, you can find the following java files (as for jmeter version 2.8):
For JUnit4:
AfterAnnotatedTest.java
BeforeAnnotatedTest.java
DummyAnnotatedTest.java
Junit4AnnotationsTest.java
For JUnit3:
RerunTest.java
SetupTestError.java
SetupTestFail.java
TearDownTestFail.java
You can see them shown up at the Classname dropdown menu on JUnit Request of JMeter (Test Plan --> Thread Group --> JUnit Request).
Those JUnit test cases are provided by JMeter by default, so I assume that a simple copy-and-paste of their code and work from there should work; however, so far, I am not able to see my test cases shown up at the Classname dropdown menu.
Here are other useful links I have found; however, none of them solves the current problem I am encountering:
Running Selenium scripts from Jmeter
http://jmeter.apache.org/usermanual/junitsampler_tutorial.pdf
JUnit test classes not showing up in JMeter
For JUnit4 the Suite would be:
#RunWith(Suite.class)
#SuiteClasses({Login.class, Logout.class})
public class LoginLogout {
private static Logger log = Logger.getLogger(LoginLogout.class.getName());
}
And the TestClass is:
public class Login {
private static Logger log = Logger.getLogger(Login.class.getName());
#Test
public void testLogin() throws Exception {
log.info("login start!");
log.info("login end!");
}
}
Worked fine for me
My unit tests are in a separate directory tree from my integration tests, but with the same package structure. My integration tests need external resources (e.g. a server) to be available, but my unit tests are properly independent of each other and the environment.
In IntelliJ-IDEA (v7) I have defined a JUnit Run/Debug Configuration to run all the tests in the top-level package, and this of course picks up my integration tests which fail.
I want to define a run-junit configuration that runs all my unit tests. Any ideas?
The answer is to create a test suite that contains only those tests underneath the unit test folder and run that instead. There is a junit-addon which does just this called DirectorySuiteBuilder but I only found this after I had pretty much re-invented the wheel.
And it's already been asked here!
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestSuite;
import java.io.File;
import java.io.IOException;
public class DirectoryTestSuite {
static final String rootPath = "proj\\src\\test\\java\\";
static final ClassLoader classLoader = DirectoryTestSuite.class.getClassLoader();
public static TestSuite suite() throws IOException, ClassNotFoundException {
final TestSuite testSuite = new TestSuite();
findTests(testSuite, new File(rootPath));
return testSuite;
}
private static void findTests(final TestSuite testSuite, final File folder) throws IOException, ClassNotFoundException {
for (final String fileName : folder.list()) {
final File file = new File( folder.getPath() + "/" +fileName);
if (file.isDirectory()) {
findTests(testSuite, file);
} else if (isTest(file)) {
addTest(testSuite, file);
}
}
}
private static boolean isTest(final File f) {
return f.isFile() && f.getName().endsWith("Test.java");
}
private static void addTest(final TestSuite testSuite, final File f) throws ClassNotFoundException {
final String className = makeClassName(f);
final Class testClass = makeClass(className);
testSuite.addTest(new JUnit4TestAdapter(testClass));
}
private static Class makeClass(final String className) throws ClassNotFoundException {
return (classLoader.loadClass(className));
}
private static String makeClassName(final File f) {
return f.getPath().replace(rootPath, "").replace("\\", ".").replace(".java", "");
}
}
IntelliJ IDEA CE 10.5 has a (new?) option to run all tests inside a configured directory:
Unfortunately there's no way to separate the output from the IntelliJ compile other than by classes and test classes within a single module (it's the classes that test runner is looking at).
So when I have integration tests I simply use a second module specific to these tests to get round this problem, specifying output directories as necessary for each module.