Create unique user for each test class run executing automation test - java

I have implemented parallel testing using Selenium and TestNG for a web application, however, my webapp got a restriction where only one session can be handled at the time (it is not supporting multi-sessions, when you login with the same user it will disconnect your older session), the solution of which I have thought to solve it is to create a unique user for each test (using API), so I have implemented it but when I am running the tests in parallel (using testng.xml file with thread-count="2") I am creating the same user twice! with the same credentials, I want to be able to create a unique user where it will create one unique user for each run.
This is my code:
public class BaseApiTest extends BaseTest {
protected String token;
protected String CREATED_ADMIN_TEST_USER;
protected String CREATED_ADMIN_TEST_PASSWORD;
private static final AtomicReference<String> ACCESS_TOKEN = new AtomicReference<>();
#BeforeClass(alwaysRun=true)
public void baseApiSetup() throws InterruptedException, ApiException {
generateToken();
createAdminUser();
}
private void generateToken() {
........
..........
...........
token = "Bearer " + ACCESS_TOKEN.get();
context.setAttribute("api-key", token);
context.setAttribute("HOST", HOST);
T_Logger.info("Host url address is: =[{}]", HOST);
T_Logger.info("new api key token =[{}]", token);
}
private void createAdminUser() throws ApiException, InterruptedException {
UsersAPIUnitTest usersAPITU = new UsersAPIUnitTest(context);
usersAPITU.createUser();
CREATED_ADMIN_TEST_USER = UsersAPIUnitTest.getEmail();
CREATED_ADMIN_TEST_PASSWORD = UsersAPIUnitTest.getPassword();
}
}
and this is used by the login page with the newly created user:
protected void adminSignIn() {
loginPage.login(CREATED_ADMIN_TEST_USER, CREATED_ADMIN_TEST_PASSWORD, true);
writeToLoggerSignIn(CREATED_ADMIN_TEST_USER);
}
and then I am starting to run my tests.
Expected: each test class will contain its own unique user
Actual: all the users that are being created are the same user with the same credentials
========================EDIT===============================
This is how I create new user:
public String createUserCms(String name, String email, String phone, String password) throws ApiException {
NewUserPayload body = new NewUserPayload();
body.setStatus(true);
body.setName(name);
body.setEmail(email);
body.setPhone(phone);
body.setPassword(password);
body.setPasswordConfirmation(password);
printBody(body);
return usersApi.createUser(token, body);
}

I have been working on a generic solution for this problem so that all automation teams can use it, still work in progress. I'm sure you would have explored other options, but creating users every time you run a test is not a good idea, rather you have to create the users once and use them otherwise you end up adding more users into your system (if you are cleaning up the users #afterMethod that's fine)
But for now, in your case, you have to make sure that you pass a unique name/email when creating the user and return that username/email address.
If you can share your createUser method snippet, we can help you more.

Related

Third-party API wrapper in Java: how to design

Suppose, there's a site that provides an API, such as this:
Users post questions, answers on that site
You can make GET and
POST calls
There are two types of authentication: weak (only gives
read rights) and strong (gives both read and write rights)
Right now, I'd like to read users' questions and answers (only need weak access) and send them messages or post my own questions in the future (would need strong access)
The site's API has actions both to do with users (e.g. send a message) and with site in general (see about, see most popular questions)
What I have right now looks like this:
public class Wrapper {
private AccessToken accessToken;
public Wrapper(...) {
//does some stuff
//gets access token:
getAccessToken(...);
}
public AccessToken getAccessToken(...) {
AccessToken result;
//gets access token, given the auth info provided as arguments
accessToken = result;
return result;
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
and User class:
class User {
private String username;
private ArrayList<Question> questions;
private ArrayList<Answer> answers;
public User(String username) {this.username=username;}
//getters and setters
}
So, to use it you would use something like this:
public class Main {
public static void main(String[] args) {
Wrapper wrapper = new Wrapper(...);
ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
wrapper.sendMessage(new User("username2"));
}
}
I have issues with this.
First of all, class User feels superfluous, since all the functionality is inside the Wrapper class.
Second, I wonder if what my methods do is wright - from the design's perspective: in getAccessToken I both return AccessToken and set a Wrapper's field accessToken to the result. Is this the right approach? Or should the method only return access token and then that result should be assigned to a class' field explicitly? Same goes for the getQuestions and getAnswers methods: they both get the ArrayLists, return them and assign a User's field to the result - all inside the single method.
I would like for a User class to have some meaning. I thought of doing it something like that:
Wrapper wrapper = new Wrapper(...);
User user = new User("username");
user.getQuestions(wrapper.getAccessToken());
user.sendMessage(wrapper.getAccessToken());
So, the Wrapper class would only serve as a place to get an access token from, which doesn't feel right as well. I could place the access token functionality inside the User class and use it like this:
User user = new User("username", ...);
user.getQuestions();
user.sendMessage();
The User's constructor would take both username and auth data, would get access token and store it inside a user and then use it when getting questions/answers or sending messages. I could make the accessToken field inside User class static so that all users shared the same token.
However, there are actions the site API provides, that aren't obviously connected with users: for instance, getting the site's most popular questions. It feels right to use a generic Wrapper class for that purpose which contradicts with the previous approach.
I'm new to this and only know a couple design patterns. Perhaps, there are widespread patterns that are to be used for this type of problem? Any help/advice is appreciated.
There are a few alternatives that you can do to solve your problem, but there is likely not one that is better than all others. The solution you choose will depend on the trade-offs and how you want your system to operate. The following are two common solutions to this type of problem.
Have the Wrapper generate a User: Instead of generating a User object separate from the Wrapper, you can have the Wrapper generate the User object. This allows the Wrapper to embed the AccessToken within the User without any outside client knowing that a user has an AccessToken. For example, you can use the following Wrapper and User definitions:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
public User(String username, AccessToken token) {
this.user = user;
this.token = token;
}
// ... getters and setters ...
}
Note that getAccessToken is now private, as no other client needs to access this method. All of the methods of Wrapper continue to accept a User argument, but they now should obtain the access token by calling getToken on the User object, rather than using a stored AccessToken in Wrapper.
Also note that the token field is final, since the access token associated with a User should not change over the life of a User object.
Embed the Wrapper in User: This technique is similar to (1), but it also embeds the Wrapper object in the User object. This allows the User class to act as a live object, which can be queried for questions and answers and can be used to send messages. Since all of the methods of Wrapper accept a User argument, this is a good sign that the methods should be moved to User. The following is a halfway point to refactor the Wrapper methods into User:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
return wrapper.getQuestions(this);
}
public ArrayList<Answer> findAnswers() {
return wrapper.getAnswers(this);
}
public boolean sendMessage() {
return wrapper.sendMessage(this);
}
// ... getters and setters ...
}
Using this technique, clients can now directly get questions and answers from a User object. Note that the findQuestions and findAnswers methods start with find. This tips off clients that this call may be a long call (as opposed to getQuestions or getAnswers, which would make a client assume that it is a simple getter and the method would return nearly-instantly). The fact that these methods execute a remote call should also be documented in the Java-docs for the methods. If the call takes a long time, the methods should return a Future (or a similar object) and be made asynchronously.
If you want to go all-in on the refactor, you can move all of the implementation details from the Wrapper class to the User class:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
// ... find the questions remotely ...
}
public ArrayList<Answer> findAnswers() {
// ... find the answers remotely ...
}
public boolean sendMessage() {
// ... send message remotely ...
}
// ... getters and setters ...
}
This may not be the best approach, as it may be a better idea to keep the details of accessing the remote API abstracted in the Wrapper class. This is a judgment call that will depend on the nature of your specific application.
There are numerous other techniques that you can do, but the above two are common approaches to the problem you are trying to solve.

Java Page Object Model Best Practices - New Objects

What is the best approach to instantiating up objects on creating steps in a Java Page Object Model?
Does anyone know how Cucumber scripts are compiled?
I would imagine if everything is built and complied the 2nd or 3rd option below may be the best approach.
If only the steps related to the test under execution are compiled then I would imagine it would be the first.
I Have the following example:
private LoginPage loginPage = new LoginPage(driver);
#Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
new HomePage(driver).clickLoginButton();
loginPage.enterEmail("test#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
new HomePage(driver).clickLoginButton();
loginPage.enterEmail("test02#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
new HomePage(driver).clickLoginButton();
loginPage.enterEmail("test03#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
All of the above steps (plus more in the same LoginSteps.java class) start with
new HomePage(driver).clickLoginButton();
Is this the best approach, or is it better to create a single instance?
private LoginPage loginPage = new LoginPage(driver);
private HomePage homePage = new HomePage(driver);
#Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test02#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test03#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
OR is it even more efficient to have the instantiation all pages in a 'baseSteps' class which LoginSteps extends?
public class LoginSteps extends BaseSteps {
#Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test02#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
#Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
homePage.clickLoginButton();
loginPage.enterEmail("test03#test.com");
loginPage.enterPassword("Password1");
loginPage.clickLogin();
}
}
public baseSteps {
protected LoginPage loginPage = new LoginPage(driver);
protected HomePage homePage = new HomePage(driver);
}
I would benchmark to see which version is most efficient.
How the Cucumber code is compiled depends on your build tool. I would assume that everything is compiled before it is being used. But a JVM that optimizes itself after some execution may behave different after a while.
I am really interested in hearing why you are thinking about performance at this level tho? Are you expecting to execute this code for hours at a time? Most of my scenarios are short, executed on the second scale and then thrown away.
Are your Cucumber tests running against the GUI? If so, it won't make a difference whether you create a single instance or multiple instances of a given Page Object. This kind of tests are slow by nature, and such a tweak will be imperceptible.
Whatever the case may be, the priority should always be a good design. As well as simplifying the future maintenance of the code, a good design will allow you to make improvements to the system performance. However, this is not true the other way around.
Cucumber and the Page Object Model fit together really well. But they should be arranged in separate layers, with Cucumber on top of the Page Object Model, acting as a client of the latter. Watching your code examples I don't understand why the Page Objects are created as part of the step definitions code. Why doesn't the clickLoginButton method itself return an instance of LoginPage?
In my opinion the Page Object Model should be supported by two basic principles:
1. API. Every Page Object should define an API with the methods corresponding to the actions a user can perform on that page.
2. Navigation. Every action should take the user to either the same page or a different page. So every method should return either the Page Object itself or a different Page Object.
The first one is fulfilled by your code, but not the second one, or at least it's not clear enough.
I would think of HomePage and LoginPage classes as something like this (without going into too much detail):
public class HomePage
{
public HomePage(WebDriver driver) {
// ...
}
public LoginPage clickLoginButton() {
perform click login button
return new LoginPage(this.driver);
}
}
public class LoginPage
{
public LoginPage(WebDriver driver) {
// ...
}
public LoginPage enterEmail(String email) {
perform enter email
return this;
}
public LoginPage enterPassword(String password) {
perform enter password
return this;
}
public NextPage clickLogin() {
perform click login
return new NextPage();
}
}
As for the Cucumber layer, I would think of it as follows (again, without going into too much detail):
private static final String PASSWORD = "Password1";
private static final String EMAIL_CUSTOMER_WITH_TWO_STORED_CARDS = "test#test.com";
private static final String EMAIL_CUSTOMER_WITH_EXPIRED_CARD = "test02#test.com";
private static final String EMAIL_CUSTOMER_WITH_THREE_STORED_CARDS = "test03#test.com";
#Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
this.performLogin(EMAIL_CUSTOMER_WITH_TWO_STORED_CARDS);
}
#Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
this.performLogin(EMAIL_CUSTOMER_WITH_EXPIRED_CARD);
}
#Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
this.performLogin(EMAIL_CUSTOMER_WITH_THREE_STORED_CARDS);
}
private void performLogin(String email) {
nextPage = homePage.clickLoginButton()
.enterEmail(email)
.enterPassword(PASSWORD)
.clickLogin();
}
See the (optional) method chaining in the last method, as a consequence of the Page Objects returned by the methods of the Page Object Model.
I have deliberately omitted the declaration of the variables homePage, loginPage and nextPage. LoginSteps does not share variables with the rest of Steps classes, even if you make them extend from a common BaseSteps class, unless you declared them as static:
public BaseSteps {
protected static HomePage homePage;
protected static LoginPage loginPage;
protected static NextPage nextPage;
...
}
Alternatively you could consider integrating a dependency injection framework, but I haven't tried myself.
Keeping the variables as private instance attributes won't work (even though they are not shared with other Steps classes) because Cucumber instantiates the Steps class for each test scenario making use of a step definition contained in the class.
Finally, there should be a hook somewhere in the Cucumber layer to initialize the entry point to the Page Object Model.
#Before
public void setUp() {
homePage = new HomePage(driver);
}
That should be the only Page Object explicitly created from the Cucumber layer.

SFTP server multiple user authentication

I am trying to extend the user authentication example, which is also presented here, so that multiple users can login to the server. I would also like to assign a different home directory for each user. So far, I haven't been able to find any such utility provided by the Apache SSHD API, so I have tried the following workaround, by using the utilities provided by the Apache FtpServer.
What I attempt to do is:
create a UserManager object to manage a list of users and store their information in a property file, in a way similar to this example
create a PasswordAuthenticator that makes use of the UserManager in its authenticate method, as follows:
public class MyPasswordAuthenticator implements PasswordAuthenticator {
private UserManager userManager;
public MyPasswordAuthenticator(){
this.userManager=null;
}
public MyPasswordAuthenticator(UserManager manager) {
this.userManager=manager;
}
#Override
public boolean authenticate(String username, String password, ServerSession session) throws PasswordChangeRequiredException {
if (this.userManager==null) return false;
User usr=null;
try {
usr = userManager.getUserByName(username);
} catch (FtpException e) {
e.printStackTrace();
}
if (usr==null) return false;
else{
String pass=usr.getPassword();
return password.equals(pass);
}
}
}
However, the usr.getPassword() returns null, even though a) the password fields in the property file do have values b) I have checked the functions getName() and getHomeDirectory() and they return their respective String values.
My question is, why does this happen and what should be done to fix this?
I have found a way to make it work, it is:
usr = this.userManager.authenticate(new UsernamePasswordAuthentication(username, password));

How do I use autologin in liferay?

I want to login my users automatically from our application. I know liferay has an auto login feature, but I don't know how to use it. I didn't find much valuable information on the web.
What do I need to do to make autologin work?
I want to login a user automaticaly when he clicks a link, without him having to enter name and password. The name and password is saved on our application database.
I believe the OP has no use for an answer now. Nonetheless, this deserves a comprehensive answer. In fact, I am surprised that it does not have one yet.
First of all, this is a bad idea: such an arrangement as the one proposed by the OP is really too insecure. Nevertheless, a solution to the described problem can be a good prototype for someone creating an autologin for Liferay.
Now, let us say you want to automatically log in any user whose screen name is sent in a query string parameter. For example, if one access http://localhost:8080/web/guest/home?insecurely_login_user=juju then the Liferay in the juju user should be logged in. How to do that? Follow the steps below:
Create the autologin class
Firstly, create a hook plugin. In its docroot/WEB-INF/src directory, creates a class implementing the com.liferay.portal.security.auth.AutoLogin interface. In my example, I will call it br.brandizzi.adam.liferay.insecure.InsecureAutoLogin.
The AutoLogin interface has only one method, called login(), which expects two parameters (an HttpServletRequest and an HttpServletResponse instances) and returns an array of strings. So, my class will look like this without implementation:
public class InsecureAutoLogin implements AutoLogin {
#Override
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
// TODO Auto-generated method stub
return null;
}
}
The AutoLogin.login() method will try to retrieve the information necessary to the authentication from many sources, mainly the request object. If it decides that the user should be logged in, it returns an array with relevant data for authentication; if it decides to not log the user in, it can just return null.
In our case, we try to get the name of the user from the the insecurely_login_user parameter from the request. If there is such parameter, we will proceed with the login; if there is no such parameter, it just returns null:
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty()) {
return null;
}
So we have the screen name. What to do now? Let us get a user from the database with the same screen name.
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
If a user wich such a screen name exists, it will be retrieved and attributed to the user variable. In this case, the authentication should be successful and the autologin class should return an array of three strings - the credentials. Those are the values to be returned as credentials, in the order they should appear in the array:
the user id as a string
the password of the user, which can be encrypted or not;
a boolean value, cast to string, indicating if the password is encrypted.
So here is the line:
return new String[] {
String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted())
};
If a user is not found, however, an exception will be thrown. So, we have to surround the code above with a try/catch construction. If an exception is thrown, just return null:
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
In the end, this is my InsecureAutoLogin class:
public class InsecureAutoLogin implements AutoLogin {
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty())
return null;
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
}
}
Registering the autologin class
Now our hook should register this class as an autologin processor. That is really easy.
First, edit the file docroot/WEB-INF/liferay-hook.xml adding a portal-properties element with the value portal.properties:
<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
</hook>
Now, create a file named portal.properties at docroot/WEB-INF/src. It should contain a property named auto.login.hooks whose value should be the name of our class:
auto.login.hooks=br.brandizzi.adam.liferay.insecure.InsecureAutoLogin
And that is it. Deploy this hook and your autologin will work.
Conclusion
As I have said, you should not use such an unsafe "authentication" method. It is too easy to bypass it, getting even administration permissions! However, if you follow these steps, you have a skeleton to create a better autologin feature. Also, I know some people really want to do something like this insecure "authentication" method and sometimes we have to suspend our judgments and just help one to shoot one's feet...
The source code of this project can be found here and you can download the WAR here.
Step 1: Create a class CustomLoginFilter and implements from AutoLogin interface.Override login method. Code as follows.
public String[] login(HttpServletRequest req, HttpServletResponse response)throws AutoLoginException {
//Get the login parameter
String loginEmailId = ParamUtil.getString(req, “_58_login”);
String password = req.getParameter(“_58_password”);
String[] credentials = new String[3];
credentials[0] = userId
credentials[1] = loginEmailId;
credentials[2] = password;
//Write your business logic Here and return String[].
}
Step 2: Write below code in portal-ext.properties
// you get full control from this custom class.
auto.login.hooks=com.bolog.portal.login.security.CustomLoginFilter
//Override Liferay Authentication pipeline
auth.pipeline.enable.liferay.check=false
auth.pipeline.pre=com.bolog.portal.login.security.CustomLoginAuthenticator
Step 3: Create class CustomLoginAuthenticator and implements from Authenticator.
Override authentication methods.
public int authenticateByEmailAddress(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByScreenName(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByUserId(long arg0, long arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
Step 4: If authentication fail then you can also redirect any page by following code
if(Validator.isNull(credentials) || credentials[0]==null){
req.setAttribute(AutoLogin.AUTO_LOGIN_REDIRECT, “Your Login page path”);
}
What exactly do you mean by "autologin"? If you want Liferay to check wheter the user is already authenticated by some external entity (like a single sign-on server as CAS), you can just enable that in the portal.properties. There it's already preconfigured for the liferay supported authentication mechanisms. Otherwise you might need to implement your own autologin hook (as indicated in this post for example
Well found it.
Step 1: Click on add iframe and let the configuration view pop up.
Step 2: Provide the url and if there are any variables like (www.mysite.com/Action=Login&User . . . .), add the Action=Login in hidden variables text field.
Step 3: Click authenticate and select form based authentication. In this, make usre that the user field name and password field name are given correctly, and the values will be '#screen_name#','#password#'.
For example, suppose the url is something like www.mysite.com/Action=Login?User=aj&Password=aj.
User Name (field)=User
Password (field)=Password
User Name (Value)=aj
Password (Value)=aj
Hidden variables(field)=Action=Login
Now, whenever any user logs into the liferay applicaiton, if his/her account exists in the site specified(in the url), it will log into that site automatically(acts like a single sign on).
This is working !!!
-Aj

TestNG - Factories and Dataproviders

Background Story
I'm working at a software firm developing a test automation framework to replace our old spaghetti tangled system.
Since our system requires a login for almost everything we do, I decided it would be best to use #BeforeMethod, #DataProvider, and #Factory to setup my tests. However, I've run into some issues.
Sample Test Case
Lets say the software system is a baseball team roster. We want to test to make sure a user can search for a team member by name.
(Note: I'm aware that BeforeMethods don't run in any given order -- assume that's been taken care of for now.)
#BeforeMethod
public void setupSelenium() {
// login with username & password
// acknowledge announcements
// navigate to search page
}
#Test(dataProvider="players")
public void testSearch(String playerName, String searchTerm) {
// search for "searchTerm"
// browse through results
// pass if we find playerName
// fail (Didn't find the player)
}
This test case assumes the following:
The user has already logged on (in a BeforeMethod, most likely)
The user has already navigated to the search page (trivial, before method)
The parameters to the test are associated with the aforementioned login
The Problems
So lets try and figure out how to handle the parameters for the test case.
Idea #1
This method allows us to associate dataproviders with usernames, and lets us use multiple users for any specific test case!
#Test(dataProvider="players")
public void testSearch(String user, String pass, String name, String search) {
// login with user/pass
// acknowledge announcements
// navigate to search page
// ...
}
...but there's lots of repetition, as we have to make EVERY function accept two extra parameters. Not to mention, we're also testing the acknowledge announcements feature, which we don't actually want to test.
Idea #2
So lets use the factory to initialize things properly!
class BaseTestCase {
public BaseTestCase(String user, String password, Object[][] data);
}
class SomeTest {
#Factory
public void ...
}
With this, we end up having to write one factory per test case... Although, it does let us have multiple users per test-case.
Conclusion
I'm about fresh out of ideas. There was another idea I had where I was loading data from an XML file, and then calling the methods from a program... but its getting silly.
Any ideas?
First, it seems like you are trying to do too much in each test case. For instance, if you are searching for something, why should you need to test navigation as part of searching?
Second, it seems like your requirements are unclear. Can you create a test where you send it a single search term and get back a single result? Seems like this should be your first test.
Third, why can't an authorized session connection/object be a requirement for a test? From the looks of your code, it looks like you are making some kind of call via HTTP. Even if you aren't, it looks like you must be using some kind of broker to send a message to your app, given that you are having to pass along user name and pass on each request... Why not just automate that whole thing into an "authorized broker" object that gives you a way to send your request along a pre-authorized connection?
Then just pass the authorized broker into your tests to handle your message passing. Or better yet, set up your authorized broker in your pre-test (BeforeMethods?) functions, and make it available as a class member variable.
I'm still not sure I understand your problem...
Are you not satisfied with your second attempt, i.e. having to write a #Factory per test case? Then why not put the #Factory annotation on the base class constructor? This way, all your subclasses need to do is call super and you're done.
What are you trying to achieve exactly?
Cederic,
I should have made an account from day one, I can't actually edit my old post anymore, or reply to comments (at this point). Let me try and expand things a little.
Here's an example of what I've come up with so far. I guess I answered my own question... this works, but its a little nasty.
My question is now, I have all my tests in one factory. That's no good for several reasons. One, I have to add them all by hand (or put them in reflectively). Two, I have to run everything essentially as one suite. Any ideas?
package example2;
import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.annotations.*;
public class WebTestBase {
protected String host, username, password;
protected HashMap<String, Object[][]> dataSet;
public WebTestBase(String host, String username, String password, HashMap<String, Object[][]> dataSet) {
this.host = host;
this.username = username;
this.password = password;
this.dataSet = dataSet;
}
#DataProvider(name="dataSet")
public Object[][] dataSet(Method m) {
return dataSet.get(m.getName());
}
#BeforeMethod
public void login() {
System.out.println("Logging in to " + host + " with " + username + ":" + password);
}
#AfterMethod
public void logout() {
System.out.println("Logging out!");
}
}
package example2;
import java.util.HashMap;
import org.testng.annotations.Factory;
public class WebTestFactory {
#Factory
public Object[] factory() {
HashMap<String, Object[][]> dataSetOne = new HashMap<String, Object[][]>();
dataSetOne.put("searchRoster", new Object[][] {
{"mcguire", "McGuire, Mark"},
{"ruth", "Ruth, Babe"}
});
HashMap<String, Object[][]> dataSetTwo = new HashMap<String, Object[][]>();
dataSetTwo.put("addPlayer", new Object[][] {
{"Sammy Sosa", 0.273}
});
Object[] tests = new Object[] {
new SearchTest("localhost", "user", "pass", dataSetOne),
new AddTest("localhost", "user", "pass", dataSetTwo)
};
return tests;
}
}
package example2;
import java.util.HashMap;
import org.testng.annotations.Test;
public class SearchTest extends WebTestBase {
public SearchTest(String host, String username, String password,
HashMap<String, Object[][]> dataSet) {
super(host, username, password, dataSet);
}
#Test(dataProvider="dataSet")
public void searchRoster(String searchTerm, String playerName) {
System.out.println("Searching for " + searchTerm);
System.out.println("I found " + playerName + " in the search results!");
}
}
package example2;
import java.util.HashMap;
import org.testng.annotations.Test;
public class AddTest extends WebTestBase {
public AddTest(String host, String username, String password,
HashMap<String, Object[][]> dataSet) {
super(host, username, password, dataSet);
}
#Test(dataProvider="dataSet")
public void addPlayer(String playerName, double battingAvg) {
System.out.println("Adding " + playerName + " with avg " + battingAvg);
}
}

Categories