I'm learning spring boot and have some tests using TestNG which run just fine when running from the IntelliJ Run Configuration, in which I pass: spring.profiles.active=dev as one of several Environment Variables.
In my Groovy Pipeline I have:
sh "./gradlew clean build test -Dspring.profiles.active=dev --no-daemon"
I have a properties file under src/main/resources:
application-dev.properties
My Spring Boot base class under src/test/java is as follows:
#SpringBootTest
public class SpringBootTestBase extends AbstractTestNGSpringContextTests {
public static Date date = new Date();
public static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
public static String dt = formatter.format(date);
public static ExtentSparkReporter spark;
public static ExtentTest test;
public static ExtentReports extent;
public static String reportDestination = "build/test-results/report_" + dt + ".html";
#BeforeSuite
public void testReport(){
spark = new ExtentSparkReporter(reportDestination);
extent = new ExtentReports();
extent.attachReporter(spark);
spark.config().setDocumentTitle("Smoke Tests");
spark.config().setReportName("Smoke Tests");
spark.config().setTheme(Theme.STANDARD);
spark.config().setTimeStampFormat("EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'");
}
#Override
#BeforeClass(alwaysRun = true)
protected void springTestContextPrepareTestInstance() throws Exception {
super.springTestContextPrepareTestInstance();
}
#AfterMethod
public void tearDown(ITestResult result) throws IOException {
if (result.getStatus() == ITestResult.FAILURE) {
test.fail(result.getName() + " test case is failed. " + "<span class='badge badge-danger'> Fail </span>" + result.getThrowable());
} else if (result.getStatus() == ITestResult.SKIP) {
test.skip(result.getName() + " test case is skipped." + "<span class='badge badge-warning'> Skip </span>");
} else if (result.getStatus() == ITestResult.SUCCESS) {
test.pass(result.getName() + " test case is Passed." + "<span class='badge badge-success'> Success </span>");
}
}
#AfterSuite
public void tearDown(){
extent.flush();
}
My Test Classes extend from this:
#SpringBootTest
public class SmokeTestOne extends SpringBootTestBase {
// test code
My main App under src/main/java:
#SpringBootApplication(exclude = MongoAutoConfiguration.class)
public class SmokeTestsApplication {
public static void main(String[] args) {
SpringApplication.run(SmokeTestsApplication.class, args);
}
}
In Jenkins, the failure is: No active profile set, falling back to default profiles: default and then a bunch of failure to Autowire beans, presumably because it cannot find the #Value attributes that need to know the active profile (environment).
A beginners error no doubt, but what am I failing to do, configuration-wise?
Related
I have 3 test methods using driver from Base class. I tired to run these methods in parallel but getting failures. Reponse to my problem is appreciated. Thanks
Class having 3 test methods
public class TestCases extends BaseClass {
#Test
public void Test1() {
homePage.checkIfElementIsDisplayed(homePage.emailElement);
homePage.checkIfElementIsDisplayed(homePage.passwordElement);
homePage.checkIfElementIsDisplayed(homePage.signInElement);
homePage.emailElement.sendKeys("karteek#gmail.com");
homePage.passwordElement.sendKeys("******");
}
#Test
public void Test2() {
homePage.checkValuesInListGroup();
homePage.checkSecondListItem();
homePage.checkSecondListItemBadgeValue();
}
#Test
public void Test3() throws InterruptedException {
homePage.ScrolltotheElement(homePage.dropDownOption);
homePage.checkDefaultSelectedValue();
homePage.selectOption3();
}
}
Base Class
public class BaseClass {
public WebDriver driver;
public HomePage homePage;
public WebDriver setup() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\resource\\GlobalData.Properties");
prop.load(fis);
String browserName = System.getProperty("browser") != null ? System.getProperty("browser")
: prop.getProperty("browser");
if (browserName.contains("chrome")) {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
}
else if (browserName.contains("edge")) {
WebDriverManager.edgedriver().setup();
driver = new EdgeDriver();
} else if (browserName.contains("firefox")) {
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
}
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().window().maximize();
return driver;
}
#BeforeMethod
public HomePage LaunchApplication() throws IOException {
driver = setup();
homePage = new HomePage(driver);
homePage.goTo();
return homePage;
}
#AfterMethod
public void tearDown() throws IOException {
driver.close();
}
I tried creating ThreadLocal Class for WebDriver as
ThreadLocal<WebDriver> threadSafeDriver=new ThreadLocal<WebDriver>();
and use this in setup() method of BaseClass by writing
threadSafeDriver.set(driver);
but this didnot really help
Most likely you are using the TestNG framework. One of the differences between JUnit and TestNG is that JUnit creates a new class instance for each test method by default but TestNG creates a single instance for all test methods in the class.
You can see the parallel option in TestNG suite (see docs) but there is no way to force TestNG to create a new instance for each test.
The simplest solution is to switch to JUnit framework. Then the code from the example should work.
I am setting up an automated framework to run tests on Android emulators, using Appium. I have added logic to launch Appium and the emulator programatically, but would like to be able to edit the "launch settings" from the TestRunner class.
My ideal goal is to have everything I need in the TestRunner class, so I can run my tests against a specific port, emulator, and tags.
But currently with the method I have now, I am receiving the following error:
'Message: cucumber.runtime.CucumberException: Hooks must declare 0 or 1 arguments.'
#CucumberOptions(
plugin = {"pretty", "html:target/cucumber-reports"}
, monochrome = true
, features = "src/test/java/feature"
, tags = "#Login"
)
public class TestRunner {
public void run() throws MalformedURLException, InterruptedException {
setUpDriver(4723, "Android9");
}
}
_________________________________________________________
public class Hooks extends DriverFactory {
static AppiumDriverLocalService service;
#Before
public static void setUpDriver(int port, String simulator) throws InterruptedException {
service = AppiumDriverLocalService
.buildService(new AppiumServiceBuilder().usingPort(port)
.usingDriverExecutable(new File("path/to/node/file"))
.withAppiumJS(new File("/path/to/appium/file")));
System.out.println("\n Appium server: " + service.getUrl());
service.start();
Thread.sleep(2000);
try {
setUpMobileDriver(simulator);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
You can pass from Maven or you can use System properties
I want to add robolectric to an existing and live android-dagger project
The problem is that the package name in the AndroidManifest is not aligned with the R file physical path.
robolectric searches for the R file according to the manifest "package_name" attribute.
I thought to use #Config over my robolectric test
#Config(manifest = " --my---path/AndroidManifest.xml",
sdk = 21,
packageName = "com.google.andorid.apps.ridematch",
application = TestApplication.class)
but apparently the "packageName" annotation is not effective.
I wanted to debug this in the robolectric open source,
but wasn't sure where was the problematic code.
It was a chance for me to first contribute to a github open-source project
my tries:
try 1)
I thought the bug is in code:
#Test
public void shouldAssignThePackageNameFromTheManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Application application = defaultTestLifecycle.createApplication(null, appManifest, null);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.wacka.wa");
assertThat(application).isExactlyInstanceOf(Application.class);
}
so I wrote this code:
#Test
public void shouldAssignThePackageNameFromConfigWhenHaveConfigAndManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Properties properties = new Properties();
properties.put("packageName", "com.robolectric.MyTestClass");
properties.put("application", "com.robolectric.TestTestApplication");
// properties.put("application", "FakeApp");
Config config = Config.Implementation.fromProperties(properties);
Application application = defaultTestLifecycle.createApplication(null, appManifest, config);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.robolectric.MyTestClass");
assertThat(application).isExactlyInstanceOf(TestTestApplication.class);
}
In "bind" i made non null config-package name override appManifest package name.
but I couldn't find who calls "defaultTestLifecycle.createApplication"
try 2)
I started looking at this class and its tests:
#Override
protected AndroidManifest getAppManifest(Config config) {
I saw this test:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package.name")
public static class PackageNameTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
and I have added mine:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package2.name", manifest = "//java/com/google/android/apps/ridematch/environments/debug:AndroidManifest.xml")
public static class PackageNameConfigAndManifestTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
but the test passed, so the bug is not there.
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
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