0

I am using Selenium and JUnit to automate tests. Lets say there are two tests and each has to authenticate with a different user and perform an action. Can it be done any smarter than to call an authentication method in each test method? Preferably with annotations so that the username for the test really stands out while skimming through the code and the login method being in @Before method or in TestBase class.

    public class AppTest extends TestBase {

    // this test must be run with userA
    @Test
    public void testA() {

        authenticateUser (userA);

        int count = retrieveNewEmailCount();
        assertEquals(NEW_EMAIL_COUNT, count);
    }

    // this test must be run with userB
    @Test
    public void testB() {

        authenticateUser (userB);

        String notificationText = retrieveNoNewEmailNotification();
        assertEquals(NO_EMAIL_NOTIFICATION, notificationText);
    }
}

Do not comment on business logic in the examples above as this is just simplified example. The real tests are not about emails at all. In reality there are hundreds of tests and almost a hundred users. Each user participates from one to hundreds tests. Each test is run once with one particular user only, ie no need to run the same test few times with different users.

2
  • What stops you from using beforemethod ?
    – PDHide
    Nov 2, 2019 at 14:01
  • @PDHide, nothing. How do I do that? How do I get a required userName in authenticateUser method if it is in Before and the userName variabble is declared in Test method?
    – lucasso
    Nov 2, 2019 at 15:29

2 Answers 2

0

You can use a bit of inheritance, which helps you to extend without dealing too much with data providers:

public abstract class AbstractTest extends TestBase{

   protected User user;

   protected AbstractTest(User user) { this.user = user; } 

   @Before
   public void setUp() {
       authenticateUser(this.user);
   }

}
public class UserWithEmailsTest extends AbstractTest {

    protected UserWithEmailsTest(User user) { super(userA); } 

    // this test must be run with userA
    @Test
    public void testA() {    
        int count = retrieveNewEmailCount();
        assertEquals(NEW_EMAIL_COUNT, count);
    }
}

public class UserWithNoEmailsTest extends AbstractTest {

    protected UserWithNoEmailsTest(User user) { super(userB); } 

    @Test
    public void testB() {
       String notificationText = retrieveNoNewEmailNotification();
       assertEquals(NO_EMAIL_NOTIFICATION, notificationText);
   }
}
3
  • Thanks for the answer, but in your example every test class has one test case, which is not suitable for our framework. As I said, there are hundreds of tests, they can not each go into separate class.
    – lucasso
    Nov 4, 2019 at 14:44
  • Not necessarily one per class: You just need to separate things that use different users. You can also inject this dependency using annotations (which is just syntactic sugar for the polymorphism above). Nov 4, 2019 at 15:15
  • can you give an example where all tests are in one class? I can not separate tests into classes by user, we have another logic for grouping tests into classes, I can not group by user.
    – lucasso
    Nov 5, 2019 at 22:03
0

Yes, there is a smarter way to authenticate with different users in Selenium JUnit tests. You can make use of JUnit's Parameterized runner and pass the authentication credentials as parameters to each test method.

Here's an example implementation:

1 Create a data provider method that returns a collection of authentication credentials (usernames and passwords).

@RunWith(Parameterized.class) public class AppTest {

@Parameterized.Parameters
public static Collection<Object[]> data() {
    return Arrays.asList(new Object[][]{
            {"userA", "passwordA"},
            {"userB", "passwordB"},
            // add more users here
    });
}

2 Add constructor to your test class to accept the parameters.

private String username;
private String password;

public AppTest(String username, String password) {
    this.username = username;
    this.password = password;
}

3 Use the username and password in the test method.

@Test
public void testEmail() {

    authenticateUser(username, password);

    int count = retrieveNewEmailCount();
    assertEquals(NEW_EMAIL_COUNT, count);
}

4 Move the authentication logic to a separate method or a TestBase class to be called by each test method.

public void authenticateUser(String username, String password) {
    // your authentication logic here
}

This way, each test method will be executed with the authentication credentials passed as parameters. This allows you to easily add new users and test cases without having to modify the test methods.

Reference:

JUnit Parameterized Tests: https://github.com/junit-team/junit4/wiki/parameterized-tests

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.