A central location for catching throwables of JUnit tests? - selenium

I would like to catch any throwable during a Selenium test e.g. in order to make a screenshot. The only solution I could come up with for now is to separately surround the test steps with a try and catch block in every test method as following:
#Test
public void testYouTubeVideo() throws Throwable {
try {
// My test steps go here
} catch (Throwable t) {
captureScreenshots();
throw t;
}
}
I'm sure there is a better solution for this. I would like a higher, more centralized location for this try-catch-makeScreenshot routine, so that my test would be able to include just the test steps again. Any ideas would be greatly appreciated.

You need to declare a TestRule, probably a TestWatcher or if you want to define the rules more explicitly, ExternalResource. This would look something like:
public class WatchmanTest {
#Rule
public TestRule watchman= new TestWatcher() {
#Override
protected void failed(Description d) {
// take screenshot here
}
};
#Test
public void fails() {
fail();
}
#Test
public void succeeds() {
}
}
The TestWatcher anonymous class can of course be factored out, and just referenced from the test classes.

I solved a similar problem using Spring's AOP. In summary:
Declare the selenium object as a bean
Add an aspect using
#AfterThrowing
The aspect can take the screenshot and save it to a
file with a semirandom generated name.
The aspect also rethrows the exception, with the exception message including the filename so you can look at it afterwards.
I found it more helpful to save the HTML of the page due to flakiness of grabbing screenshots.

Related

KotlinLogging Throws NoSuchMethod Exception

I'm using this library:
"io.github.microutils:kotlin-logging:2.0.4"
with this logging implementation:
"ch.qos.logback:logback-classic:1.2.3"
In my code I call:
private val logger = KotlinLogging.logger{}
and then use this logger as follows:
logger.debug("message")
this runs fine until I try to debug my code at which point the following to two NoSuchMethodErrors pop up in the library:
private static IMarkerFactory bwCompatibleGetMarkerFactoryFromBinder() throws
NoClassDefFoundError {
try {
return StaticMarkerBinder.getSingleton().getMarkerFactory();
} catch (NoSuchMethodError var1) {
return StaticMarkerBinder.SINGLETON.getMarkerFactory();
}
}
And:
private static MDCAdapter bwCompatibleGetMDCAdapterFromBinder() throws
NoClassDefFoundError {
try {
return StaticMDCBinder.getSingleton().getMDCA();
} catch (NoSuchMethodError var1) {
return StaticMDCBinder.SINGLETON.getMDCA();
}
}
(the first time I try to log something)
Others on my team do not experience this issue. they are on macs, in case that matters.
If, I just continue running the code everything is fine as the exception is caught, but I don't want to hit continue twice anytime I want to debug. I'm willing to ignore exceptions if that is possible, or better yet, fix the underlying issue.

A proper way to conditionally ignore tests in JUnit5?

I've been spotting a lot of these in my project's tests:
#Test
void someTest() throws IOException {
if (checkIfTestIsDisabled(SOME_FLAG)) return;
//... the test starts now
Is there an alternative to adding a line at the beginning of each test? For example in JUnit4 there is an old project that provides an annotation #RunIf(somecondition) and I was wondering if there is something similar in JUnit5?
Thank you for your attention.
Tests can be disabled with #DisabledIf and a custom condition.
#Test
#DisabledIf("customCondition")
void disabled() {
// ...
}
boolean customCondition() {
return true;
}
See also the user guide about custom conditions.

How to Take Screenshot when TestNG Assert fails?

String Actualvalue= d.findElement(By.xpath("//[#id=\"wrapper\"]/main/div[2]/div/div[1]/div/div[1]/div[2]/div/table/tbody/tr[1]/td[1]/a")).getText();
Assert.assertEquals(Actualvalue, "jumlga");
captureScreen(d, "Fail");
The assert should not be put before your capture screen. Because it will immediately shutdown the test process so your code
captureScreen(d, "Fail");
will be not reachable
This is how i usually do:
boolean result = false;
try {
// do stuff here
result = true;
} catch(Exception_class_Name ex) {
// code to handle error and capture screen shot
captureScreen(d, "Fail");
}
# then using assert
Assert.assertEquals(result, true);
1.
A good solution will be is to use a report framework like allure-reports.
Read here:allure-reports
2.
We don't our tests to be ugly by adding try catch in every test so we will use Listeners which are using an annotations system to "Listen" to our tests and act accordingly.
Example:
public class listeners extends commonOps implements ITestListener {
public void onTestFailure(ITestResult iTestResult) {
System.out.println("------------------ Starting Test: " + iTestResult.getName() + " Failed ------------------");
if (platform.equalsIgnoreCase("web"))
saveScreenshot();
}
}
Please note I only used the relevant method to your question and I suggest you read here:
TestNG Listeners
Now we will want to take a screenshot built in method by allure-reports every time a test fails so will add this method inside our listeners class
Example:
#Attachment(value = "Page Screen-Shot", type = "image/png")
public byte[] saveScreenshot(){
return ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
}
Test example
#Listeners(listeners.class)
public class myTest extends commonOps {
#Test(description = "Test01: Add numbers and verify")
#Description("Test Description: Using Allure reports annotations")
public void test01_myFirstTest(){
Assert.assertEquals(result, true)
}
}
Note we're using at the beginning of the class an annotation of #Listeners(listeners.class) which allows our listeners to listen to our test, please mind the (listeners.class) can be any class you named your listeners.
The #Description is related to allure-reports and as the code snip suggests you can add additional info about the test.
Finally, our Assert.assertEquals(result, true) will take a screen shot in case the assertion fails because we enabled our listener.class to it.

Infrom Selenium that feature file starts \ ends

I have to make some operations when a Feature file starts or ends.
But I didn't find any way that Selenium can know it.
Meanwhile I use a specific hook tag to catch the beginning and another one to catch the end. But Is there a way to know it in Selenium code?
You can use before and after hook to perform some actions, you can add extra tag to your cucumber scenario and check it by scenario.getSourceTagNames(). see the example below:
#Before
public void setUpScenario(Scenario scenario) {
List<String> tags = scenario.getSourceTagNames();
if (tags.contains(scenario_specific_tag)) {
System.out.println("Before your scenario running ...." );
}
}
#After
public void endUpScenario(Scenario scenario) {
List<String> tags = scenario.getSourceTagNames();
if (tags.contains(scenario_specific_tag)) {
System.out.println("After your scenario ...." );
}
}

arquillian warp timing out instead of executing AfterPhase (or AfterServlet, BeforePhase or BeforeServlet for that matter)

I am just getting started with Arquillian Warp and seems to have hit a stumbling block.
I have a basic UI Test for a registration page
#WarpTest
#RunWith(Arquillian.class)
public class TestProfileEdit extends AbstractUsersTest {
#Drone
FirefoxDriver browser;
#Page
EditProfilePage editProfilePage;
#Page
LoginPage loginPage;
#ArquillianResource
private URL baseURL;
#Deployment
public static Archive<?> createLoginDeployment() throws IOException {
// trimmed for brevity
}
#Before
public void setup() throws MalformedURLException{
final URL loginURL = new URL(baseURL, "login.jsf");
browser.navigate().to(loginURL);
loginPage.login("test#domain.com", "password");
final URL pageURL = new URL(baseURL, "profile/edit.jsf");
System.out.println(pageURL.toExternalForm());
browser.navigate().to(pageURL);
}
#After
public void tearDown() {
browser.manage().deleteAllCookies();
}
#Test
#RunAsClient
public void testSaveData() {
editProfilePage.getDialog().setFirstName("Test First Name");
Warp.execute(new ClientAction() {
#Override
public void action() {
editProfilePage.getDialog().save();
}
}).verify(new TestProfileOnServer());
}
#SuppressWarnings("serial")
public static class TestProfileOnServer extends ServerAssertion {
#Inject
private EntityManager em;
#Inject
private Identity identity;
#Inject
Credentials credentials;
#AfterPhase(Phase.RENDER_RESPONSE)
public void testSavedUserProfile() {
System.out.println("RUNNING TEST");
String username = identity.getUser().getId();
TypedQuery<UserProfile> q = em.createQuery(
"SELECT u from UserProfile u where u.userIdentity.name like :username", UserProfile.class);
UserProfile p;
p = q.setParameter("username", username).getSingleResult();
assertEquals("Test First Name", p.getFirstName());
}
}
}
I have tried the various combinations on testSavedUserProfile() method with absolutely no luck in getting that to trigger.
The test always ends with
java.lang.IllegalStateException: java.util.concurrent.ExecutionException: org.jboss.arquillian.warp.client.execution.AssertionHolder$ServerResponseTimeoutException
I can see the page getting posted and redirected correctly on the firefox window that gets opened up. I tried to get it to not redirect etc. and nothing has helped.
I feel like I am missing something basic and simple but no idea what!
Any help much appreciated.
Thanks.
I've recently encountered a similar problem with Arquillian Warp.
One of the reasons my code didn't get called was that Arquillian merges the server-sde servlet filter into a web archive (WAR) deplyoment only. Neither EAR nor JAR deployments work off the shelf.
For my concrete problem (EAR deployment) I modified the test classes in a way that I merge in the Arquillian filter myself when assembling the tested WAR which in turn is packed into an EAR deployment.
The other problem I ran across was that the AfterServlet event is simply not fired within the unit test execution scope but as part of the servlet filter cleanup code. I believe this logic is totally broken and I build a private fork of the servlet filter which IMHO is handling the logic correctly.