You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When developing a plugin, the best way to test plugin is without loading the WordPress environment. If you write code that can be easily tested without WordPress, your code becomes better.
Every component that is unit tested, should be tested in isolation: when you test a class, you only have to test that specific class, assuming all other code is working perfectly.
So, testing in isolation means testing a component (class in this case) at a time without loading any external dependencies. Those external dependencies can even be other classes in same plugin.
This is the reason why unit tests are called "unit". Also, without loading core, tests will run much faster which will be a huge benefit if we integrate unit tests in our CI/CD pipeline because deployment job will be completed much quicker
Example of problem
Consider there are two classes School and Student. Suppose, School class have some method register for admission of new student.
Note: I'm not writing Student class because it is not required for explaining the issue.
Now, suppose you want to test School class in isolation (according to definition given above), register_student method would not be feasible to test because your tests have to be aware of Student class' structure in order to test register_student method which contradicts the idea of testing in isolation.
Here, we can deal with this situation by passing Student object to register_student method directly as
publicfunctionregister_student( Individual$student ) {
// Do something with student object below
}
Individual is an interface because a school can have different individuals like Employees, Students, Vendors etc. and all will have some common properties and methods like name, gender, age etc.
Above method can be easily tested using Mock, we can pass Student mock to register_student method in order to test that method. In this case, our test class do not need to have knowledge of Student class' structure in order to test School class and thus we achieve Testing in isolation 🥳
Another solution
Other solution can be to use Factory pattern to get objects build. So we can create a separate factory class/method to get Student object.
register_student in above example can also be tested because we can mock the factory class while testing the School class and can pass that mock to School's constructor via dependency injection.
Actual issue in current code
filter_search_query method in class-search.php is instantiating class Search_Engine inside its body, so it will be difficult to test in isolation as shown above.
Golden rule
Never instantiate any class inside method body. Either use Factories or use DI, so that code should be testable in unit.
The text was updated successfully, but these errors were encountered:
Create a factory class called SearchEngineFactory inside that we will implement functionality to instantiate the SearchEngine class object.
Create an object of this factory in the main class file i.e. class-plugin.php
Inject/Pass the factory object wherever it is required in our case to the Search class.
Define a factory class variable as suggested in the above example. And whenever required use this factory object to create the instance/fetch the object of SearchEngine class.
TLDR
What the heck does "Testing in isolation" mean?
When developing a plugin, the best way to test plugin is without loading the WordPress environment. If you write code that can be easily tested without WordPress, your code becomes better.
Every component that is unit tested, should be tested in isolation: when you test a class, you only have to test that specific class, assuming all other code is working perfectly.
So, testing in isolation means testing a component (
class
in this case) at a time without loading any external dependencies. Those external dependencies can even be other classes in same plugin.This is the reason why unit tests are called "unit". Also, without loading core, tests will run much faster which will be a huge benefit if we integrate unit tests in our CI/CD pipeline because deployment job will be completed much quicker
Example of problem
Consider there are two classes
School
andStudent
. Suppose,School
class have some methodregister
for admission of new student.Note: I'm not writing
Student
class because it is not required for explaining the issue.Now, suppose you want to test
School
class in isolation (according to definition given above),register_student
method would not be feasible to test because your tests have to be aware ofStudent
class' structure in order to testregister_student
method which contradicts the idea of testing in isolation.Here, we can deal with this situation by passing
Student
object toregister_student
method directly asIndividual
is an interface because a school can have different individuals like Employees, Students, Vendors etc. and all will have some common properties and methods like name, gender, age etc.Above method can be easily tested using Mock, we can pass
Student
mock toregister_student
method in order to test that method. In this case, our test class do not need to have knowledge ofStudent
class' structure in order to testSchool
class and thus we achieveTesting in isolation
🥳Another solution
Other solution can be to use Factory pattern to get objects build. So we can create a separate factory class/method to get
Student
object.and our
School
class can be something likeregister_student
in above example can also be tested because we can mock the factory class while testing theSchool
class and can pass that mock toSchool
's constructor via dependency injection.Actual issue in current code
filter_search_query
method inclass-search.php
is instantiating classSearch_Engine
inside its body, so it will be difficult to test in isolation as shown above.Golden rule
Never instantiate any class inside method body. Either use Factories or use DI, so that code should be testable in
unit
.The text was updated successfully, but these errors were encountered: