A proper way to conditionally ignore tests in JUnit5? - testing

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.

Related

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.

Abort/ignore parameterized test in JUnit 5

I have some parameterized tests
#ParameterizedTest
#CsvFileSource(resources = "testData.csv", numLinesToSkip = 1)
public void testExample(String parameter, String anotherParameter) {
// testing here
}
In case one execution fails, I want to ignore all following executions.
AFAIK there is no built-in mechanism to do this. The following does work, but is a bit hackish:
#TestInstance(Lifecycle.PER_CLASS)
class Test {
boolean skipRemaining = false;
#ParameterizedTest
#CsvFileSource(resources = "testData.csv", numLinesToSkip = 1)
void test(String parameter, String anotherParameter) {
Assumptions.assumeFalse(skipRemaining);
try {
// testing here
} catch (AssertionError e) {
skipRemaining = true;
throw e;
}
}
}
In contrast to a failed assertion, which marks a test as failed, an assumption results in an abort of a test. In addition, the lifecycle is switched from per method to per class:
When using this mode, a new test instance will be created once per test class. Thus, if your test methods rely on state stored in instance variables, you may need to reset that state in #BeforeEach or #AfterEach methods.
Depending on how often you need that feature, I would rather go with a custom extension.

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 ...." );
}
}

A central location for catching throwables of JUnit tests?

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.

In MSTest how to check if last test passed (in TestCleanup)

I'm creating web tests in Selenium using MSTest and want to take a screenshot everytime a test fails but I don't want to take one every time a test passes.
What I wanted to do is put a screenshot function inside the [TestCleanup] method and run it if test failed but not if test passed. But how do I figure out if a last test passed?
Currently I'm doing bool = false on [TestInitialize] and bool = true if test runs through.
But I don't think that's a very good solution.
So basically I'm looking for a way to detect if last test true/false when doing [TestCleanup].
Solution
if (TestContext.CurrentTestOutcome != UnitTestOutcome.Passed)
{
// some code
}
The answer by #MartinMussmann is correct, but incomplete. To access the "TestContext" object you need to make sure to declare it as a property in your TestClass:
[TestClass]
public class BaseTest
{
public TestContext TestContext { get; set; }
[TestCleanup]
public void TestCleanup()
{
if (TestContext.CurrentTestOutcome != UnitTestOutcome.Passed)
{
// some code
}
}
}
This is also mentioned in the following post.