#DataProvider ignores the #BeforeTest and #AfterTest methods - webdriver

I have the following code:
#BeforeTest(alwaysRun = true)
public void setup() {
System.out.println("#BeforeTest");
}
#DataProvider
public String[][] provideData() {
System.out.println("#DataProvider");
return new String[][] {
{"string"},
{"string2"},
{"string3"}
};
}
#Test(dataProvider = "provideData")
public void test(String s) {
System.out.println("#Test");
System.out.println(s);
}
#AfterTest(alwaysRun = true)
public void tearDown() {
System.out.println("#AfterTest");
}
which produces the following output to the console:
#BeforeTest
#DataProvider
#Test
string
#Test
string2
#Test
string3
#AfterTest
I was expecting the #BeforeTest and #AfterTest methods to run before and after the test. I am writing WebDriver tests and would like to setup and teardown after each iteration of the data. What am I missing?

I think I have figured this out. I have a theory that the #BeforeTest and #AfterTest are only going to execute after ALL of the runs of the parameterized test are done, because there is only one #Test annotation. Changing this to #BeforeMethod and #AfterMethod seems to give the output I want:
#DataProvider
#BeforeTest
#Test
string
#AfterTest
#BeforeTest
#Test
string2
#AfterTest
#BeforeTest
#Test
string3
#AfterTest
I believe this is because the data provider sees this as a single test, but the method is executed multiple times, so it follows the before and after sequence appropriately.

It looks like you're using TestNG, but you're used to JUnit. Here's a table that explains the annotations a bit more.
http://www.mkyong.com/unittest/junit-4-vs-testng-comparison/

You can use BeforeMethod and AfterMethod for this.

Related

PowerMockito mockStatic gives MissingMethodInvocationException

I am trying to mockStatic method using PowerMockito , where I tried some options to mockStatic for a class, resulting in different exceptions.
#RunWith(PowerMockRunner.class)
#PrepareForTest({Base64.class})
public class BqClientFactoryTest {
#Test
public void testGetBigQueryClient() throws Exception {
mockStatic(Base64.class);
Base64.Decoder mockDecoder = mock(Base64.Decoder.class);
when(Base64.getDecoder()).thenReturn(mockDecoder);
This resulted in org.mockito.exceptions.misusing.MissingMethodInvocationException:
I used another example like this
#RunWith(PowerMockRunner.class)
#PrepareForTest({Base64.class})
public class BqClientFactoryTest {
#Test
public void testGetBigQueryClient() throws Exception {
mockStatic(Base64.class);
Base64.Decoder mockDecoder = mock(Base64.Decoder.class);
doReturn(mockDecoder).when(Base64.class, "getDecoder");
which gives me
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
If I use
BDDMockito.given(Base64.getDecoder()).willReturn(mockDecoder);
from Mocking static methods with Mockito , it still returns org.mockito.exceptions.misusing.MissingMethodInvocationException
I tried to check similar questions on SO, they haven't seemed to help.
Any help resolving this is appreciated.
I solved it following this, all other solutions didn't work for me. It is difficult to search for this solution, since there are too many on SO on the same.
PowerMockito mock single static method and return object inside another static method , PowerMock, mock a static method, THEN call real methods on all other statics
#RunWith(PowerMockRunner.class)
#PrepareForTest({Base64.class})
public class BqClientFactoryTest {
#Test
public void testGetBigQueryClient() throws Exception {
Base64.Decoder mockDecoder = mock(Base64.Decoder.class);
stub(method(Base64.class, "getDecoder")).toReturn(mockDecoder);

Unable to use the Page Object in a Test Method. (TestNG)

I m somebody who to new to Automation. I m currently learning Selenium Webdriver with JAVA along with Page Object Model pattern. When I experimenting with the few lines of code I got myself strucked at one point. I created a separate class file for the Page Elements which has the below code.
public class SamplePage {
WebDriver Driver;
public WebElement Gmail_Email_TextBox = Driver.findElement(By.xpath(".//*[#id='Email']"));
public WebElement Gmail_Email_Next_Button = Driver.findElement(By.xpath(".//*[#id='next']"));
public SamplePage(WebDriver Driver) { //This is a constructor.
System.out.println("Constructor");
this.Driver = Driver;
}
}
When try call the above page in another class I get java.lang.NullPointerException. Pls find the code below.
public class SampleTestMethod {
WebDriver Driver;
#BeforeMethod
public void BrowserLaunch() throws InterruptedException {
Driver = Browser.LaunchMozillaFirefox("https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1");
}
#Test
public void TestCase1() {
SamplePage Sample1 = new SamplePage(Driver);
Sample1.Gmail_Email_TextBox.click();
}
}
Pls clarify me on this. The constructor is not being called at all. This is what I have observed.
Class fields like Gmail_Email_TextBox and Gmail_Email_Next_Button are evaluated as null before constructor's call and never changed afterwards. That is why.
Simply put: initialize those fields in a different place.
You can add a #FindBy annotation to each of them and then just use PageFactory:
SamplePage samplePage = new SamplePage();
PageFactory.initElements(driver, samplePage);
Further info on this.
Follow naming conventions and use camelCase.
Instance variables are initialized before constructor calls.
Check this out to see it yourself:
public class Example {
private String instanceVariable;
private String anotherInstanceVariable = instanceVariable + " appended.";
public Example(String instanceVariable) {
this.instanceVariable = instanceVariable;
}
public static void main(String[] args) {
Example example = new Example("The first one");
System.out.println(example.anotherInstanceVariable);
}
}
instanceVariable is like your driver. anotherInstanceVariable is like any of your WebElements.

Selenium WebDriver -Tests that use other tests

As an example, I have:
#Test
public void login(*Code ommitted*){
That tests logging into a site.
Then I want to do other tests that start with logging in, so I've got:
#Test
public void sendUserInvite(){
login();
*Other code omitted*
}
Something is intuitively telling me this is really bad practise, but at the same time if the login test does what I need it to, so why not re-use it in this way? Can anyone clarify this. After a while I end up doing several tests at the start of another test because they are the pre-conditions in order to carry out a particular test.
If you're using TestNG, you can use #BeforeClass, #BeforeSuite, #BeforeTest, #BeforeMethod etc. in order to launch your preconditions on some step before your #Test method
E.g. you have 2 tests in xml:
<suite name="Suite0" verbose="1" >
<test name="name0" >
<classes>
<class name="Test0" />
</classes>
</test>
<test name="name1">
<classes>
<class name="Test1"/>
</classes>
</test>
</suite>
Let's assume Test0 and Test1 both extend class BaseTest
Then in BaseTest:
public class BaseTest {
#BeforeTest
public void login() {
// smth w/ login
}
}
So, when the suite is launched, login method will be invoked. Just note that #BeforeTest will work for every test from a suite, not for every method with #Test, this sometimes confuses.
UPD
If you're using JUnit, you can use #Before, and method with it will be run before every #Test in a class. So to say, it is the same as #BeforeMethod in TestNG
#Before
public void pre() {
// your login here
}
#Test
public void testA() {
// prints A
}
#Test
public void testB() {
// prints B
}
#After
public void end() {
// logout
}
Order of execution:
login
A
logout
login
B
logout
According to the following links, JUnit test cases are designed to be run in isolation and each test should be independent of one other. I believe you have to reconsider your design and go for test framework like TestNG which perfectly suites your requirements.
Choose order to execute JUnit tests
running a subset of JUnit #Test methods
How to run test methods in specific order in JUnit4?
If you feel the need to call one test method from another test method, that's a good sign that you need to extract a class.
I suggest moving login to a PageObject class:
public class HomePage {
private final WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
}
public WelcomePage login(String userName, String password) {
signIn(userName, password);
Assert.assertEquals("sign in failed", userName, getSignedInUser());
return new WelcomePage(driver, userName);
}
private void signIn(String userName, String password) {
// Add code to perform the sign in
}
public String getSignedInUser() {
// Add code to check the current page to see who is reported
// as the signed in user
}
}
Then your test looks like this:
#Test
public void login() {
HomePage page = new HomePage(driver);
page.login(TEST_USER_NAME, TEST_PASSWORD);
}
#Test
public void sendUserInvite() {
WelcomePage page = new HomePage(driver)
.login(TEST_USER_NAME, TEST_PASSWORD);
page.sendUserInvite(NON_USER_EMAIL_ADDRESS);
}
Of course, your page objects may also have some code duplication (for instance, getting the signed in user may be a common concern). When this happens, you can either extract a base class for all of our page objects or a helper class for common logic.

movckmvc test that correct error message returned

The following test (testing that validation fails as the terms and conditions accepted by the user is not latest version) works fine but I would like to test the error message that's returned. The reason for this is a subsequent test (check that validation fails if accepted terms and conditions version is null) will have the same test criteria.
As a result I would also like to test the error message that's returned. I've spent the whole morning searching for somethign and cannot find anything which makes me wonder whether it's even possible to access/test error message values? I can see it's within the Model but am struggling to access/test it.
Any help would be appreciated!
Thanks in advance
S
TEST
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({ "file:src/main/webapp/WEB-INF/spring-servlet.xml" })
public class FailureRegistrationControllerTest {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
public void acceptedVersionIsNotTheLatestTest() throws Exception {
//Create the DTO User
UserRegistrationDTO user = TestingUtility.createMinimumUserDTO();
user.setTermsAndConditionsVersion(TestingConstants.NOT_LATEST_TERMS_AND_CONDITIONS);
//Run the test
ResultActions resultActions = TestingUtility.buildResultsActionsMinimum(mockMvc, user);
resultActions.andExpect(status().isOk());
resultActions.andExpect(view().name("register"));
resultActions.andExpect(model().attributeHasFieldErrors("user", "termsAndConditionsAccepted"));
}
I was trying to solve similar problem once but I have only not very official solution. I have checked the code how they are doing it and I have found out that any errors are stored inside the model prefixed with BindingResult.MODEL_KEY_PREFIX, see their code:
private BindingResult getBindingResult(ModelAndView mav, String name) {
BindingResult result = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);
assertTrue("No BindingResult for attribute: " + name, result != null);
return result;
}
so you are able to obtain it from model and check details...

order of reporting of tests in testng report is random

This is how my testNG test looks like:-
public class orderTest{
#Test
public void meth1() throws InterruptedException{
System.out.println("1");
Reporter.log("1");
}
#Test
public void meth2() throws InterruptedException{
System.out.println("2");
Reporter.log("2");
}
#Test
public void meth3() throws InterruptedException{
System.out.println("3");
Reporter.log("3");
}
#Test
public void meth4() throws InterruptedException{
System.out.println("4");
Reporter.log("4");
}
}
When i run it on eclipse, the console shows as :-
1
2
3
4
PASSED: meth1
PASSED: meth2
PASSED: meth3
PASSED: meth4
But when i open the testNG report, click on reporter output link, it shows as :-
Reporter output -
meth1
1
meth4
4
meth3
3
meth2
2
Why the order is not correct in the testng report?
order of execution is 1,2,3,4
but,
order of reporting is 1,4,3,2.
It can also be displayed by execution order in the output report. To do so, your TestNG Reporter should implement IReporter.
A good plugin that uses it is ReportNG.
You can override it's generateReport method, to display the suites in the Html report, by their parent XML suite order, like so:
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectoryName) {
...
Comparator<ISuite> suiteComparator = new TestSuiteComparator(xmlSuites);
suites.sort(suiteComparator);
...
}
Where the TestSuiteComparator is as follow:
public class TestSuiteComparator implements Comparator<ISuite> {
public List<String> xmlNames;
public TestSuiteComparator(List<XmlSuite> parentXmlSuites) {
for (XmlSuite parentXmlSuite : parentXmlSuites) {
List<XmlSuite> childXmlSuites = parentXmlSuite.getChildSuites();
xmlNames = new ArrayList<String>();
xmlNames.add(parentXmlSuite.getFileName());
for (XmlSuite xmlsuite : childXmlSuites) {
xmlNames.add(xmlsuite.getFileName());
}
}
}
#Override
public int compare(ISuite suite1, ISuite suite2) {
String suite1Name = suite1.getXmlSuite().getFileName();
String suite2Name = suite2.getXmlSuite().getFileName();
return xmlNames.indexOf(suite1Name) - xmlNames.indexOf(suite2Name);
}
}
If you want the classes and methods listed in this file to be run in an unpredictible order, set the preserve-order attribute to false.
That is what the TestNG documentation says, so unless the wrong spelling (not saying that mine is perfect :), that's a feature.
But it seems to me, that only the reporting order is unpredictable, the execution seems quite predictable.
The dtd says,
#attr preserve-order If true, the classes in this tag will be run in the same order as
found in the XML file.
so that matches what it actually does.
It's not wrong but maybe expected the other way round.
Seems to be a feature to make the reports more attractive :)

Resources