In my last post, we learned about Abstraction and how to use it in Test Automation framework. In continuation to the same, this post will focus on another key pillar of OOP - Encapsulation. 

The readers will be able to take away the following leanings from this post:

- What is Encapsulation?

- How Encapsulation is different from Abstraction?

- How to implement encapsulation?

- What are the benefits of encapsulation?

- How can we use encapsulation in a test automation framework?

Before moving to the next section, if you have not read the part 1 post of this series, I would encourage you to read the same from this link OOPs concept in Test Automation Design Part 1 - Abstraction.

What comes to our mind when some one said the word Capsule? In most simplest way, we can define a capsule as a small container with some drug or other substances inside it, which is used for medical or scientific purposes. We consume capsule as per the advice of doctor. Just think about a situation what will happen if manufactures of any capsule allow to manipulate the ingredients inside a capsule by the consumers? Without any second thought we will say it is very risky. Each capsule comes up with a protection cover for a purpose. Same thing applies for software world. Luckily we have encapsulation as protection cover which helps us to protect the data belongs to a specific component. In object oriented world, we define encapsulation as a process of binding data and methods that can control the data together into a single unit (class). The designer of the unit (or class) can decide what kind of access it may allow to the outsiders and how that can be achieved.

In first go, encapsulation may seems to be similar to Abstraction. Let's dig little more deeper with some real life example.

Example: I am on a business travel and my travel suite case containing both personal as well as business specific things inside. I got the default lock key when I purchased the suite case and I have changed the code as per my convenience. 

What is abstracted in this example?

As the owner of the suite case, I know how to operate the suite case (open and close), how to set the lock code and how to unlock it.  I really do not bother how the suite case was manufactured till it solves my purpose of using the same. I also do not care how locking/unlocking happens internally if I can perform it with ease. 

What is encapsulated in this example?

I have my personal things inside the suite case which only I know and I want to protect those from others (except may be the baggage checker at the airport). I want to wrap my things in a neat way inside the suite case and whenever I want something I should be able to take it out without much effort.  I want to make sure I should be able to unlock the suite case with the code I have set. Here is the sample java code:

In the above example key pointers to look for are as below:

- The access modifiers for lockCode and lockStatus instance variables are private (we want to protect those data)

- We have public method for setting the lock code. (Everyone should be able to set the lock code for their suite case)

- We have private method for getting the lock code which is only used internally. (We kept it private so that is used only by internal methods)

- We have public method for unlocking the suite case with correct lock code. (Everyone should be able to unlock their suite cases providing correct lock code set by them)

Since now we have some good context on what encapsulation is, here are some the key differences between abstraction and encapsulation :

- Abstraction hides complexity but encapsulation hides data by controlling the visibility.

- Abstraction is more inclined towards design level where as encapsulation is more inclined towards implementation level.

- Abstraction provide information about what a component supposed to do where as encapsulation helps to achieve it in a control manner using data binding with methods.

Implementation

    So far we understood that encapsulation is hiding of internal data and allows connecting with other components with predefined boundaries and contracts. This can be implemented using access modifies (Java example: public, private, protected and default). Access modifiers enables us to control the behavior of classes, object creation, methods and variables.  It is allowed to use combinations of access modifiers together in a single class for different entities. We can just add the modifier as prefixing it to the declaration of class, variables and methods.

Here are some ways we can implement encapsulation in code:

- Using private variables

- Using getter and setter methods 

- Using read only class (only getter methods will be provided)

- Using write only class (only setter method will be provided)

Encapsulation in Test Automation

We are using encapsulation in many places in test automation framework. 

Scenario 1 : Page class in page object model. 


In the above LoginPage class, encapsulation has been implemented. I have added a main method to test the class. Please note in real framework we will have test classes where we create objects of page classes and call the allowed methods to perform various operations.

- All the variables in this class are private, means we do not want them to be modified by out side classes for example usernameTxt instance variable.

- In this example, we have not provided explicit getters and setters since we are not doing any manipulation on the locator variables. There is actually no need to expose those properties to the test class in this context and encapsulation helps here.

- We are providing public methods to interact with the locators from the outside class and perform necessary actions for example the performLogin() method.

Scenario 2 : Parsing config properties

Java has Properties class which can be used to set or get properties from .properties config file. Here is the link to the java doc of Properties class https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html . This class has public getter and setter like setProperty and getProperty which is again an example of encapsulation.

Benefits of encapsulation

- Encapsulation makes the code modular by binding data and methods to manipulate that data under one unit (class).

- Encapsulation allows the designer to be flexible to take a call on what to protect and what to expose to the outside of the unit based on design decisions. 

- Helps in maintaining data integrity by preventing unintentional data modification or corruption.

How to select right access level in the code?

Thinking about the right access modifiers to use helps to understand the big picture of how objects of different classes are going to interact with each other.

- We should declare the instance variables (attributes or fields) as private and provide public getter setters methods if we want to give controlled access to the calling class objects.

- If we do not want to modify the state of the object, read only class (only with getter methods) can help.

If we want to modify the the state of the object but do not care about getting that state back, we can use write only class (only with setter methods). Some of you may ask why do we need a write only class in the first place? How this will help? Let's consider an example from Java Random class. This class has a method to seed the value of a given random number. This actually alters the state of the random number generator object. Providing a method to return the seed which has been set by the object actually does not makes sense and also not provided in the class. Another example could be if we are creating a drawing object with provided coordinates, it makes sense to provide the setters than getters. 

- Protected variables and methods should be used only if sub class absolutely needs those.

- Internal methods used in a class as support methods to the main logics should be always private.

Is it possible to access private methods/properties from outside the class?

Answer is both yes and no. We cannot directly access private method/properties from outside the class. We should respect to the reason behind adding the private access to those. But some time we may need to access those for unit testing purpose. In Java we can use Java reflection APIs to call a private method from another class.


Congratulation, you have reached the end of this post and thank you so much for your time. Feel free to share your thoughts and comments on how are you using encapsulation in your code so that we can learn together. My next post will be on Inheritance, see you soon :-)