The POM is a model of the web application, so, if you have a complex applicaiton, the model will naturally reflect that. I have been involved in the testing of web applications with many page objects (tens if not more), with large forms, and with many steps required to perform a test - it can be challenging but is possible. My examples are based on Java, but should be applicable to any OO language.
Should I still make each step/page a Class?
I would say yes, you should make each page a class. This generally helps with maintainability and readability. Protip: If you aren't considering it already, then consider using usecases, as a layer between the step definitions, and the page objects.
The page objects may have methods like enterUsername(), enterPassword(), clickSubmit(). A usecase called CreateUserUC may have methods like createUser() which invokes the page object methods previously mentioned. And, finally, your step definition will call createUserUC.createUser(name, pass). That's not the best example but I've seen it help with reusability of methods especially where there are lots of steps, and forms which appear at various stages of the workflows.
In a page with a ton of forms, should each "Input" be a definition/method?
I would also say yes, have a setter for each input. Again, this helps with maintainability. However, please consider the following example form.
- List item
- firstName
- middleName
- lastName
- addressLine1
- addressLine2
- addressLine3
Here we can easily abstract out a name object and an address object. In this case, I would create classes for both of those objects, and my Page Object would contain the following methods:
- public void enterName(Name name)
- public void enterAddress(Address address)
- private void enterFirstName(String firstName)
- private void enterMiddleName(String middleName)
- private void enterLastName(String lastName)
- private void enterAddressLine1(String addressLine1)
- private void enterAddressLine2(String addressLine2)
- private void enterAddressLine3(String addressLine3)
The first 2 methods would invoke the private methods. People might call this overkill, but in my experience it's safer to be overkill than to have insufficient structure and insufficient flexibility for change.
or should I initialize the class with all the inputs defined in the constructor?
I would certainly not recommend this approach, having said that I can understand the appeal. You can hide the details of setting all the fields within a usecase method. Typically I believe that the constructor for a page object should be used to set up the model of the page, if anything needs to be done, and that any interactions with the page (like filling in a form) should be done by calling methods after construction. This helps with maintainability.
Since the pages are mostly forms + Submit button....what should the methods in the class be?
This is standard for web applications. Methods of the page object should be along the lines of:
- public void enterFirstName(String firstName)
- public void enterName(Name name)
- public String getErrorMessage()
- public void checkSuccessMessagePresent()
- public void clickSubmit()
Since a "Script" of creating the widget would be 7-8 different steps...would I just be creating 7-8 different POM objects in the script?
Yes. I'd say the above examples should help so I will just summarize with:
- Consider usecases. They should be high level enough that they are succinct but also low level enough so you can reuse them and that they provide value
- Consider abstracting out objects entered in the forms, and try to operate more with those instead (Address, Name) of the fine detail of every form (firstName, etc.).
- Look for common items in the web application, perhaps certain types of forms are reused. You can have a partial page object, and then a page object may contain several partial page objects.
- Keep in mind the web application could change regularly so try to write clean code, having each method do just one thing.