SlideShare una empresa de Scribd logo
1 de 78
Descargar para leer sin conexión
BDD and browser automation with
Geb and Spock
Данилюк Богдан
Jeeconf | may 2014 | @bogdand
Главный вопрос жизни
вселенной и всего такого
Главный вопрос жизни
вселенной и всего такого
Как в любой момент быть уверенным в
качестве текущей версии вашего
приложения и дать возможность людям
понять что же оно делает?
Кто я?
● C Groovy / Grails начиная с 2008 года
● Успешно внедрили и используем Geb /
Spock
● - Groovy / Grails курс
● Первый разработчик в TransferWise,
сейчас 100+ человек
TransferWise
TransferWise
С чего все начиналось?
≈ 0% покрытие тестами
С чего все начиналось?
Smoke testing
● Тестировалось <10 страниц
● Время прохождения тестов ≈1 минута
● Обнаруженных ошибок - мало =)
Smoke testing
Geb
very groovy browser automation
Geb
● Groovy обертка вокруг Selenium 2
● Лицензия ASL2
● Текщая версия: 0.9.2
● Дружит с JUnit и Spock
● Groovy Page object
● http://gebish.org
Geb - WebDriver
● Мобильные браузеры:
○ iPad
○ iPhone
○ Android
○ Blackberry
● PhantomJS
● HtmlUnit
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Простой Geb test
go "http://www.google.com"
$("input", name: "q").value("JeeConf")
$("button", name: "btnG").click()
waitFor { $("div", id: "search").displayed }
assert $("div", id: "search").text()
.contains("jeeconf.com")
Метод $()
$(«css selector», «index or range», «attribute / text matchers»)
Примеры
$("div") // все div элементы
$("div", 0) // первый div элемент
$("div", 0..2) // первых три div элемента
// Третий H2 элемент с текстом “Geb”
$("h2", 2, text: "Geb")
CSS3 селекторы
$("div.some-class p:first[title='some']")
$("ul li a")
$("table tr:nth-child(2n+1) td")
$("div#content p:first-child::first-line")
Атрибуты
Поиск по атрибутам
//<div foo="bar">
$("div", foo: "bar")
Атрибуты
Поиск по атрибутам
//<div foo="bar">
$("div", foo: "bar")
Поиск по тексту
//<div>foo</div>
$("div", text: "foo")
Навигация
Поиск по атрибутам
//<div foo="bar">
$("div", foo: "bar")
Поиск по тексту
//<div>foo</div>
$("div", text: "foo")
Поиск по регулярным выражениям
//<div>foo</div>
$("div", text: ~/f.+/)
Вспомогательные функции
$("p", text: startsWith("p"))
$("p", class: contains("section"))
$("p", id: endsWith(~/d/))
Больше примеров в документации
Относительный поиск
$("p").previous()
$("p").prevAll()
$("p").next()
$("p").parent()
$("p").siblings()
$("div").children()
$("p").nextAll(".listing")
Functional testing
Functional testing
● Время прохождения тестов - 20 минут
● Обнаруженных ошибок - уже больше =)
● Грядут редизайны веб страниц
Geb
Страницы и модули
Page Object
class WikipediaPage extends Page {
static url = "https://www.wikipedia.org"
static at = { title == "Wikipedia" }
static content = {
search { $("#searchInput") }
}
}
Page Object
class WikipediaPage extends Page {
static url = "https://www.wikipedia.org"
static at = { title == "Wikipedia" }
static content = {
search { $("#searchInput") }
}
}
Page Object
class WikipediaPage extends Page {
static url = "https://www.wikipedia.org"
static at = { title == "Wikipedia" }
static content = {
search { $("#searchInput") }
}
}
Page Object
class WikipediaPage extends Page {
static url = "https://www.wikipedia.org"
static at = { title == "Wikipedia" }
static content = {
search { $("#searchInput") }
}
}
Page Object использование
Browser.drive {
to WikipediaPage
assert at(WikipediaPage)
search = "JeeConf"
}
Опциональный контент
class OptionalPage extends Page {
static content = {
errorMsg(required: false) { $("p.errorMsg") }
}
}
Динамический контент
class DynamicPage extends Page {
static content = {
errorMsg(wait: true) { $("p.errorMsg") }
}
}
Наследование Page Object
● Блоки content будут слиты
● Методы унаследуются
Повторное использование
● Блоки, повторяющиеся на многих
страницах
● Блоки,
повторяющиеся
на одной
странице
Объявление модуля
class NavBarModule extends Module {
static content = {
homePageLink(to: HomePage) { $("a#home") }
profileLink(to: ProfilePage) { $("a#profile") }
}
}
Использование модулей
class HomePage extends Page {
static content = {
navBarModule { module NavBarModule }
}
void goToProfilePage() {
navBarModule.profileLink.click()
}
}
Пример moduleList
class ProfilePage extends Page {
static content = {
paymentListTable {moduleList PaymentRow,
$("table#paymentList tbody tr")}
}
}
class PaymentRow extends Module {
static content = {
amount { $("td.amount") }
status { $("td.status") }
}
}
Проблема поддержки
to HomePage
loginButton.click()
username = "user"
password = "password"
loginButton.click()
Page Object builder
● Подход предложен Craig Atkinson
● По умолчанию Geb делегирует вызовы
методов текущей странице
● Билдер делает эти вызовы явными
Page Object builder
HomePage homePage = to HomePage
LoginPage loginPage = homePage.clickLoginButton()
DashboardPage dashboardPage = loginPage.login("user",
"password")
HomePage homePage = to HomePage
DashboardPage dashboardPage = homePage.clickLoginButton().
login("user", "password")
Вызов по цепочке
Реализация HomePage
class HomePage extends Page {
static content = {
loginButton(to: LoginPage, wait: true) {
$("#loginButton")
}
}
LoginPage clickLoginButton() {
loginButton.click()
return browser.page
}
}
Geb + Spock
Архитектура
App
Browser
WebDriverGeb
geb-spock
(Testing adapter)
Spok
Spock тест
class GoogleSpec extends GebReportingSpec {
def "the first link should be wikipedia"() {
when:
to GoogleHomePage
q = "wikipedia"
then:
at GoogleResultsPage
firstResultLink.text() == "Wikipedia"
when:
firstResultLink.click()
then:
waitFor { at WikipediaPage }
}
}
Spock data-driven тест
when:
LoginPage loginPage = loginAsUser(username)
then:
assert loginPage.error == expectedErrorMessage
where:
username | expectedErrorMessage
'disabledUser' | 'Sorry, your account is disabled'
'lockedUser' | 'Sorry, your account is locked'
'invalidUser' | 'Sorry, we could not find that account'
Проблемы
● Тестировались в основном длительные
цепочки страниц
● Вся подготовка данных делалась через
веб интерфейс
Некрасивый тест
class LoginSpec extends GebReportingSpec {
def "login"() {
given: "a valid user"
go RegistrationPage
register("user", "password")
logout()
when: "the user logins with valid credentials"
go LoginPage
login("user", "password")
then: "the welcome page is displayed"
at DashboardPage
}
Некрасивый тест
class LoginSpec extends GebReportingSpec {
def "login"() {
given: "a valid user"
go RegistrationPage
register("user", "password")
logout()
when: "the user logins with valid credentials"
go LoginPage
login("user", "password")
then: "the welcome page is displayed"
at DashboardPage
}
Use case тестирование
Чего мы хотим?
● Результат тестов не булевое значение
● Экранирование сценариев
● Упор на документирование
● Привлечение нетехнических
специалистов для работы с тестами
Экранирование сценариев
Чего мы хотим достигнуть?
● Каждый тест готовит данные для себя
● Тест должен знать как можно меньше
информации о внутренностях
приложения
● Тест не должен ломаться при
рефакторингах
Первая идея
А давайте обновлять базу?
Проблемы:
● Тесты знают много низкоуровневой
информации о приложении
● Тысты очень чуствительны к
изменениям в приложении
Remote control
Groovy remote control
“is a library for executing closures defined in one
Groovy application to be executed in a different
(possible remote) Groovy application.”
Remote control - сервер
def receiver = new Receiver()
def handler = new RemoteControlHttpHandler(receiver)
def server =
HttpServer.create(new InetSocketAddress(8080), 0)
server.createContext("/groovy-rc", handler)
server.start()
Remote control - сервер
def receiver = new Receiver()
def handler = new RemoteControlHttpHandler(receiver)
def server =
HttpServer.create(new InetSocketAddress(8080), 0)
server.createContext("/groovy-rc", handler)
server.start()
Remote control - сервер
def receiver = new Receiver()
def handler = new RemoteControlHttpHandler(receiver)
def server =
HttpServer.create(new InetSocketAddress(8080), 0)
server.createContext("/groovy-rc", handler)
server.start()
Remote control - клиент
def transport =
new HttpTransport("http://example.org:8080/groovy-rc")
def remote = new RemoteControl(transport)
def id = remote {
def user = new User(name: "Me", password: "pwd")
user.save()
user.id
}
Remote control - клиент
def transport =
new HttpTransport("http://example.org:8080/groovy-rc")
def remote = new RemoteControl(transport)
def id = remote {
def user = new User(name: "Me", password: "pwd")
user.save()
user.id
}
Remote control - клиент
def transport =
new HttpTransport("http://example.org:8080/groovy-rc")
def remote = new RemoteControl(transport)
def id = remote {
def user = new User(name: "Me", password: "pwd")
user.save()
user.id
}
Remote control - клиент
def transport =
new HttpTransport("http://example.org:8080/groovy-rc")
def remote = new RemoteControl(transport)
def id = remote {
def user = new User(name: "Me", password: "pwd")
user.save()
user.id
}
Некрасивый тест
class LoginSpec extends GebReportingSpec {
def "login"() {
given: "a valid user"
go RegistrationPage
register("user", "password")
logout()
when: "the user logins with valid credentials"
go LoginPage
login("user", "password")
then: "the welcome page is displayed"
at DashboardPage
}
Красивый тест
class LoginSpec extends GebReportingSpec {
def "login"() {
given: "a valid user"
remote {
SpringUtils.getRegisterService()
.register("user", "password")
}
when: "the user logins with valid credentials"
go LoginPage
login("user", "password")
then: "the welcome page is displayed"
at DashboardPage
Отчеты
Стандартный Grails отчет
Стандартный Grails отчет
Spock отчеты
Требования
● Логическая групировка тестов
● Возможность запуска группы тестов
● Человекочитаемая документация
Пример отчета
Spock отчеты
Решение
● Расширили Athaydes Spock Reports
○ Добавили группировку
○ Возможность запуска группы
спецификаций
@Group('Invite program')
@SpecName('Invitee')
class InviteesSpec extends GebBaseSpec {
def "Invitee should get a free payment"() {
when: "user register with invite link"
then: "user has one free payment"
}
}
Что дальше?
● Тестирование верстки
● Ускорение тестов
● Переход на Gherkin (Cucumber) для
избежания дублирования коментариев и
кода
class InviteesSpec extends GebBaseSpec {
def "Invitee should get a free payment"() {
when: "registered with invite link user"
registeredWithInviteLinkUser()
then: "user has one free payment"
to AccountPage
freePayments.text().contains("1")
}
}
Вопросы?
Всего хорошего, и
спасибо за рыбу!

Más contenido relacionado

La actualidad más candente

Ice Php Framework Preview Release
Ice Php Framework Preview ReleaseIce Php Framework Preview Release
Ice Php Framework Preview ReleaseDenis Shestakov
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Ontico
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.Igor Shkulipa
 
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evroneit-people
 
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)Как мы ускоряли WebGL / Мстислав Живодков (2GIS)
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)Ontico
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Paul Klimov
 
Как не утонуть в мегабайтах JS-кода
Как не утонуть в мегабайтах JS-кодаКак не утонуть в мегабайтах JS-кода
Как не утонуть в мегабайтах JS-кодаtfmailru
 
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...tfmailru
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agencyit-people
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервереYandex
 
QA Fest 2015. Иван Пашко. XPath yourself. Tips & Tricks
QA Fest 2015. Иван Пашко. XPath yourself. Tips & TricksQA Fest 2015. Иван Пашко. XPath yourself. Tips & Tricks
QA Fest 2015. Иван Пашко. XPath yourself. Tips & TricksQAFest
 
Изоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьИзоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьCodeFest
 
Общая архитектура Yii2
Общая архитектура Yii2Общая архитектура Yii2
Общая архитектура Yii2Paul Klimov
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Paul Klimov
 
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлению
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлениюCodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлению
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлениюCodeFest
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииPaul Klimov
 
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
вебинар - функциональное тестирование с использованием Selenium 2 и TestNGвебинар - функциональное тестирование с использованием Selenium 2 и TestNG
вебинар - функциональное тестирование с использованием Selenium 2 и TestNGAndrey Rebrov
 

La actualidad más candente (20)

Ice Php Framework Preview Release
Ice Php Framework Preview ReleaseIce Php Framework Preview Release
Ice Php Framework Preview Release
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.
 
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
 
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)Как мы ускоряли WebGL / Мстислав Живодков (2GIS)
Как мы ускоряли WebGL / Мстислав Живодков (2GIS)
 
course js day 4
course js day 4course js day 4
course js day 4
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2
 
Как не утонуть в мегабайтах JS-кода
Как не утонуть в мегабайтах JS-кодаКак не утонуть в мегабайтах JS-кода
Как не утонуть в мегабайтах JS-кода
 
JSSDK: Начало
JSSDK: НачалоJSSDK: Начало
JSSDK: Начало
 
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...
Технологии тестирования Rich Web client, Андрей Плешков, Форум Технологий Mai...
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере
 
QA Fest 2015. Иван Пашко. XPath yourself. Tips & Tricks
QA Fest 2015. Иван Пашко. XPath yourself. Tips & TricksQA Fest 2015. Иван Пашко. XPath yourself. Tips & Tricks
QA Fest 2015. Иван Пашко. XPath yourself. Tips & Tricks
 
Изоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьИзоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесь
 
Общая архитектура Yii2
Общая архитектура Yii2Общая архитектура Yii2
Общая архитектура Yii2
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
 
Суперсилы Chrome developer tools
Суперсилы Chrome developer toolsСуперсилы Chrome developer tools
Суперсилы Chrome developer tools
 
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлению
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлениюCodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлению
CodeFest 2013. Родионов А. — От Selenium к Watir — путь к просветлению
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляции
 
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
вебинар - функциональное тестирование с использованием Selenium 2 и TestNGвебинар - функциональное тестирование с использованием Selenium 2 и TestNG
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
 

Similar a 2014 Jeeconf - Geb Spock

Selenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euSelenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euAndrei Solntsev
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов ИгорьPVasili
 
Web internship java script
Web internship   java scriptWeb internship   java script
Web internship java scriptNoveo
 
jQuery. Введение и практика
jQuery. Введение и практикаjQuery. Введение и практика
jQuery. Введение и практикаSlava Aliev
 
Как стать продуктивным Android разработчиком
Как стать продуктивным Android разработчикомКак стать продуктивным Android разработчиком
Как стать продуктивным Android разработчикомPavel Shchahelski
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11dva
 
Web осень 2012 лекция 4
Web осень 2012 лекция 4Web осень 2012 лекция 4
Web осень 2012 лекция 4Technopark
 
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2GoQA
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCDevDay
 
Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Anton Arhipov
 
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серыйVladislav Morgun
 
I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_schoolITmozg
 
Python Meetup
Python Meetup Python Meetup
Python Meetup iQSpace
 
Svyatoslav Login "360 View of XSS"
Svyatoslav Login "360 View of XSS"Svyatoslav Login "360 View of XSS"
Svyatoslav Login "360 View of XSS"Fwdays
 
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...Andrey Rebrov
 
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDBCodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDBCodeFest
 
Серверный JavaScript: NodeJS и CouchDB
Серверный JavaScript: NodeJS и CouchDBСерверный JavaScript: NodeJS и CouchDB
Серверный JavaScript: NodeJS и CouchDBStepan Stolyarov
 
Batch processing in rails
Batch processing in railsBatch processing in rails
Batch processing in railssergeymoiseev
 

Similar a 2014 Jeeconf - Geb Spock (20)

Selenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.euSelenide puzzlers @ devclub.eu
Selenide puzzlers @ devclub.eu
 
JavaScript как объектно-ориентированный язык программирования
JavaScript как объектно-ориентированный язык программированияJavaScript как объектно-ориентированный язык программирования
JavaScript как объектно-ориентированный язык программирования
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
 
Jsfwdays 2013-2
Jsfwdays 2013-2Jsfwdays 2013-2
Jsfwdays 2013-2
 
Web internship java script
Web internship   java scriptWeb internship   java script
Web internship java script
 
jQuery. Введение и практика
jQuery. Введение и практикаjQuery. Введение и практика
jQuery. Введение и практика
 
Как стать продуктивным Android разработчиком
Как стать продуктивным Android разработчикомКак стать продуктивным Android разработчиком
Как стать продуктивным Android разработчиком
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11
 
Web осень 2012 лекция 4
Web осень 2012 лекция 4Web осень 2012 лекция 4
Web осень 2012 лекция 4
 
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2
СВЯТ ЛОГИН «Як провести пошук на xss атаку» Online QADay 2020 #2
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
 
Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)
 
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый
08.11 SEMPRO Club - Влад Моргун - Цвет настроения серый
 
I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_school
 
Python Meetup
Python Meetup Python Meetup
Python Meetup
 
Svyatoslav Login "360 View of XSS"
Svyatoslav Login "360 View of XSS"Svyatoslav Login "360 View of XSS"
Svyatoslav Login "360 View of XSS"
 
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
 
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDBCodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
 
Серверный JavaScript: NodeJS и CouchDB
Серверный JavaScript: NodeJS и CouchDBСерверный JavaScript: NodeJS и CouchDB
Серверный JavaScript: NodeJS и CouchDB
 
Batch processing in rails
Batch processing in railsBatch processing in rails
Batch processing in rails
 

2014 Jeeconf - Geb Spock