Before this is all
Hey. I am Dima and I do not know the patterns. As for the tester, do not say that it is problematic. As for automator ..? Well, let's be honest, you can live too.
From chatikov, conferences and communication with colleagues, it is clear: the main pattern - PageObject - learned, what else do you need?
And here there was such a big paragraph of thinking about why we, in fact, do not use design patterns: do we not know them or are we good at them without them? There were also deepening in the history that the patterns are not for you, but for decades proven knowledge and methods, arguments for and the mention of famous comrades who are against.
But, ultimately, knowledge of the patterns just does not hurt.
So, by no means encouraging you to embed patterns in the code everywhere, I begin to publish a series of articles on patterns.
A little more about the format and go
The articles / books / video courses on patterns are quite decent for themselves. And I am sure you will easily find a resource with a competent explanation, examples on your favorite YAP, emelyaks, etc.
The task of this and subsequent articles: to tell about the patterns to those who are already working with the code, but do not have a good base on the theory. So these articles, perhaps, for me, first of all.
Well, since I myself am a tester, and in my circle of contacts there are quite a few of the same, the stories will be with a bias towards testing automation.
Some of the patterns will seem strange and not very useful. And with some people, on the contrary, you will find that you are realizing something like this for a long time, only you didn’t know that this is the name.
In any case, I hope you find something useful for yourself.
And yes, I will be very happy constructive criticism in the comments.
Here it is.
- about himself - told
- what will be - told
- why - told
- for whom and how - told
You can start.
Proxy - Proxy - Deputy
Theory (slightly)
Proxy pattern (in Russian editions,
Deputy ). The idea is to produce for work not a real object, but a substitution that uses the methods of the object + our logic, if we add one. Everything.
How it's done:
1. Create an interface with public methods of the object that we want to replace
2. Create a class that
- implements this interface
- has access to the original object to call its methods.
3. Add our logic to the methods of the created class
Practice
In practice, it should be clearer.
Given: We have a WebDriver. And he has a method findElements (By by);
Task: I really need to log how many items were found by the selector.
Every time I call the method
driver.findElements(By.cssSelector(".item"));
I want to see a record in the logs - how many items were found
Solution 1. In the forehead. What is really there: I applied it.
Just take and, with each call, we write how many were found:
List<WebElement> items = driver.findElements(By.cssSelector(".item")); logger.info("Found {} items", items.size());
The option is normal, as long as there are such calls, let's say, 7. Although it’s already unpleasant and the disadvantages of this approach are obvious to anyone who has “slightly modified his code” at least once.
Solution 2. Use a proxy.
WebDriver is an interface. Methods declared, but no implementation. Implementations include ChromeWebDriver, FirefoxWebDriver, etc.
We, in tests, do not have to work with any particular class for chrome or safari. It is only necessary that the class implement the interface WebDriver. This will do:
Create an interface with public methods of the object that we want to replace
In our example, this interface is already there - WebDriver.
Create a class that
- implements this interface
- has access to the original object to call its methods.
public class LoggerWebDriver implements WebDriver{ private WebDriver driver; public void get(String s) { } public List<WebElement> findElements(By by) { return null; } public WebElement findElement(By by) { return null; }
Add your logic to the methods of the created class
public class LoggerWebDriver implements WebDriver { private WebDriver driver; private final Logger logger = LogManager.getLogger(LoggerWebDriver.class); LoggerWebDriver() {
What happened?Added to class
private WebDriver driver;
This is the object that we want to replace. It is his methods that we will call forth.
Now, you can see, for example, the method
public void get(String var1) { driver.get(var1); }
All that the method does is call get () on the real driver.
But the method
public List<WebElement> findElements(By var1) { List<WebElement> items = driver.findElements(var1); logger.info("Selector {}. Found {} elements", var1.toString(), items.size()); return items; }
we expanded according to our task.
That's all, you can use the tests:
WebDriver driver = new LoggerWebDriver(); driver.get("http://google.com"); List<WebElement> items = driver.findElements(By.cssSelector("a"));
Here it is. The pattern is good if you need to add logging, caching, lazy initialization, access control to methods. In general, if you are writing code and you really want to have some kind of layer with your features, one of the options is a proxy.
Now, when we know one more pattern, let me remind you that when a hammer is in hand, everything seems to be nails. Just remember this.