Let's assume that you are working in an automation project that is quite large.
There are many page classes in the project and many test classes.
To reduce code duplication that happens mostly in page classes, the project uses one (or more) utility classes.
Typically, a utility class has lots of methods for
interacting with frames
interacting with browser windows and tabs
waiting and interacting with elements (click, sendKeys, etc)
interacting with elements having specific html
parsing data
filtering data
selecting data
reloading the current page
generating date/time values
interacting with drop down lists
waiting until the page is loaded
scrolling to elements, to the top of the page or bottom
generating random data
retrying actions on web elements
In some cases, the utility class may also include
methods that create test data using APIs
methods that query databases
Also, you may find in the utility class
methods that interact with specific pages
methods that navigate to specific pages
page factory web elements
methods that implement site workflows
As you imagine, the more methods you add to it, the larger the utility class becomes.
But it does the job. It allows code duplication to be minimized as the utility class provides handy methods to be used in the page classes.
You may look at the utility class (es) as being your automation framework.
This is incorrect, though.
A utility class (or more) is not a framework, not at all.
Let's see why.
1. A framework is a collection of small and focused classes organized in packages.
For example, jUnit 4 uses the following packages:
org.hamcrest
org.hamcrest.core
org.junit
org.junit.experimental
org.junit.experimental.categories
org.junit.experimental.max
org.junit.experimental.results
org.junit.experimental.runners
org.junit.experimental.theories
org.junit.experimental.theories.suppliers
org.junit.function
org.junit.matchers
org.junit.rules
org.junit.runner
org.junit.runner.manipulation
org.junit.runner.notification
org.junit.runners
org.junit.runners.model
org.junit.runners.parameterized
org.junit.validator
Each package includes other packages.
Each package is focused on a specific group of classes.
Each class has a single focus.
For example, the Assert class is only about assertions.
2. The framework is documented in a Java Doc.
3. The framework is packaged as a JAR file
4. The framework relies on dependencies that are maintained in a pom.xml file (by Maven).
5. The framework is 100% independent of the project and can be used without changes by multiple projects.
6. The framework is versioned.
Compare all these with the utility class.
The utility class is usually very big and not focused at all.
It is actually more a code repository than a class since its methods have different purposes.
The utility class does not have documentation as a JavaDoc.
The utility class cannot be deployed as a JAR file.
The utility class relies on the dependencies of the automation project, it does not have its own dependencies.
The utility class is most of the time dependent on the project that it is part of.
There is no way the utility class can be versioned being a class among many classes of the automation project.
A utility class is not a framework.
If you want to have an automation framework, the first thing to do is to get rid of the utility class.