Post on 22-Jan-2018
АВТОТЕСТЫ В
ФУНКЦИОНАЛЬНОМ
СТИЛЕ
КОНСТАНТИН НЕРАДОВСКИЙСБЕРБАНК ТЕХНОЛОГИИ
kneradovsky@gmail.com
telegram: @kneradovsky
ПОЧЕМУ
• Линейный код - что вижу, то пою.
• Много copy-n-paste. «копирование велосипедов»
• Assertions покрывают только «стандартные» проверки. Поэтому
не используется
• Низкое качество кода. NullPointerException бывает чаще чем кофе.
• Реиспользуемость - что это?
КАК?
• StreamAPI - коллекции
• Optional - исключает NullPointerException
• Лямбда выражения в WebDriverWait - исключает неожиданные
ElementNotFoundException
• Словари проверок - нет copy-n-paste
• Частичное применение функций - повышает реиспользуемость
• Лямбда выражения в Assert - удобные проверки
ПРИНЦИПЫ
ФУНКЦИОНАЛЬНЫЙ ПОДХОД
• First-Class Functions - функции как объекты.
• High-Order Functions - функции порождают функции
• Pure functions - результат зависит только от аргументов
• Closures - фиксирование контекста
• Immutable state неизменяемое состояние.
v = function a() {
return «a»;};
vf = function b() {
return v;};
function sum(a,b) {
return a+b;};
out = «outside»;
f = function c() {
return out+«a»;};
obj = function concat(o1,o2) {
return o3 = o1+o2;};
АНОНИМНЫЙ КЛАСС - РЕАЛИЗАЦИЯ ИНТЕРФЕЙСА
ЛЯМБДА ВЫРАЖЕНИЯ
(входные параметры) -> {реализация метода интерфейса}
Лямбда Анонимный класс
Predicate<String> t = s -> s.equals(«test»);
Predicate<String> t = new Predicate<String> {
public boolean test(String s) {
return s.equals(«test»);}
Runnable r = () -> {System.out.println(«a»);}
Runnable r = new Runnable {
public void run() {
System.out.println(«a»);}
Function<Integer,String> c = i -> i.toString();
Function f = new Function<Integer,String> {
String apply(Integer i) {
return i.toString();}
ЗАМЫКАНИЯ И ВЫЗОВ
ЛЯМБДА ВЫРАЖЕНИЯ
Замыкание
final String label = "element contents";
Predicate<WebElement> p = e -> e.getText().equals(label);
Вызов
Определение Вызов
Predicate<String> t = s -> s.equals(«test»); boolean result = t.test(«string1»);
Function<WebElement,String> m = e -> e.getText(); String text = m.apply(element);
Consumer<WebElement> c = e -> {e.click();} c.accept(element);
ФУНКЦИОНАЛЬНЫЕ ИНТЕРФЕЙСЫ
Java.util.function• Consumer<T> – принять o -> {code;}
• Supplier<R> - вернуть () -> new MyObject()
• Function<T,R> – принять и вернуть o -> o.toString()
• Predicate<T> – принять что-то и вернуть boolean o -> o.equals(expected)
Любой интерфейс с одним методом• Runnable () -> {code;}
• Comparable<T> o -> o.toString().compareTo(expected);
• и т.д.
NPE no more
OPTIONAL
Optional Эквивалент
ClassA c = ofNullable(a).orElse(b); ClassA c = a!=null ? a : b;
ClassA c = ofNullable(a).orElseGet(()->new
ClassA());ClassA c = a!=null ? a : new ClassA();
ClassA c = ofNullable(a).orElseThrow(() -> new
AutotestError(«Error»));
ClassA c = a!=null ? a : throw new
AutotestError(«Error»)
JVM MAGIC
METHOD REFERENCE
Method Reference Пример Эквивалент
WebElement::getTextFunction<WebElement,String> t =
WebElement::getText
Function<WebElement,String> t
= element -> element.getText()
ClassA::new Supplier<ClassA> s = ClassA::newSupplier<ClassA>
s = () -> new ClassA();
УДОБНАЯ РАБОТА С ДАННЫМИ
STREAM API
Коллекция
list.stream()
Генерация
Stream.generate
sum, min, joining
groupingBy
reduce
collect …
java.uti l .stream
TRY – CHECKED EXECUTION AND STREAM API FOR OBJECTS
JAVASLANG
Try.of - аналог Optional.ofNullable, но перехватывает исключения
Try.of(ClassA::new).onFailure(exception -> {process exception});
Try.run - выполняет блок и перехватывает исключения
Try.run(()->element.click()).onFailure(e-> processException)
Try.filter - аналог Stream.filter, но для объектов
Try.of(ClassA::new).filter(ClassA::isEnabled).orElse(null);
Try.map - аналог Stream.map, но для объектов
Try.of(ClassA::new).filter(ClassA::toString).orElse(«default string»);
List<WebElement>.stream()
КОЛЛЕКЦИИ
Найти все видимые элементы .filter(WebElement::isDisplayed).toArray()
Вернуть текст элементов .map(WebElement::getText).toArray()
Отобрать все элементы с id=1.filter(e->e.getAttribute(«id»).equals(«1»))
.toArray()
Function<Predicate<WebElement>,BaseMatcher<WebElement>> m
ASSERTS
Элемент el enabled assertThat(el,m.apply(WebElement::isEnabled))
Элемент el видим assertThat(el,m.apply(WebElement::isDisplayed))
Класс элемента содержит
class
assertThat(el,
m.apply(e->e.getAttribute(«class»).contains(«class1»)))
Q&A
СПАСИБО
… AND LET’S CODE
https://github.com/kneradovsky/java8fp_samples
kneradovsky@gmail.com
telegram: @kneradovsky
https://habrahabr.ru/post/301166/