How to abstract data classes to be more object oriented?



  • I have run into problems keeping my tests as object-oriented as possible. I have had to rewrite large portions of my code multiple times now, and I feel that there is a better approach to what I'm doing. I explain my design below.

    Description:

    I am using Selenium/Java to do some data integrity testing. The website being tested is used to create and manipulate batches. These batches have various properties such as name, ID number, different quantities, and ingredients. This data for each batch is supposed to change and be updated as you progress through the workflow of the website. The Selenium tests are supposed to simulate the workflow and track the batches to verify the data integrity of the website.

    Current design:

    I am using the Page Object Model to abstract the page classes from the test classes. In addition, I have a Batch class with all the properties and getters/setters for most properties. In all applicable page classes, I have a scrapeBatch() method which scrapes the batch information and returns a new Batch() object with those properties set. I then have an equals(Batch) method defined for the Batch object to verify that there are no discrepancies between two batches. The scrapeBatch() methods for the page classes right now use setters to assign the properties to a new Batch() object. In addition, different pages on the website display different properties.

    Goal:

    I would like to not have to use all the getters and setters to make the code more concise and to reuse more code wherever possible. I have read that using interfaces is the way to go, but I am having difficulty understanding how to define those interfaces in the most logical way. Any suggestions for ways to refactor my code would be greatly appreciated. I would be able to expand more on this too, if that is needed.



  • You are right to be concerned about getters/setters; they are an anti-pattern in OOP and should be avoided because they result in more tightly coupled code

    Instead invert the responsibility by using the tell don't ask idiom. In this case use an expected data manager. Create a Batch class that reflects the expected data and pass this expectedData to the pageObject for validation. The page object scrapes the data items and passes the values to the Batch object for verification.

    public class Batch {
        private Data expectedData;
    
        public void verify(Data actual) {
           assertEquals(expectedData, actual);
        }
    }
    

    When I use an expected data manager I give it factory method to make the instance of the class, loading the data for the specific context by use of tag. e.g. '@scenarioName'.

    public class MyPageObject extends AbstractPageObject {
        @FindBy(id="dataId")
        private WebElement pageItem;
    
        public void verify(Batch batchData) {
           batchData.verify(pageItem);
        }
    }
    


Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2