пятница, 1 ноября 2013 г.

Что такое CDN и для чего она нужна


CDN это сеть доставки контента (Content Delivery Network). Под словом контент в данном случае подразумеваются статические ресурсы, которые мы используем на сайте: JavaScript, стили (CSS), картинки, flash (SWF) файлы, и другие документы.

А под словами Сеть доставки подразумевают набор серверов разнесенных географически (географически распределённая сетевая инфраструктура). Файлы на таких серверах синхронизируются и при необходимости пользователя получить файл – сервера между собой решают, кто будет отдавать файл. 
А зачем?
  1. Экономия траффика (кэширование). На серверах CDN очень хорошо работает кэширование файлов. Например, пользователь зашел на сайт1, а потом на сайт2 и после этого зашел к нам на сайт. Если все три сайта используют один и тот же CDN, то библиотека загрузится только один раз, а все остальные разы она будет браться из локального кэша. Пользователь сэкономит несколько килобайт траффика и порадуется тому, как у него быстро загружаются сайты.
  2. Увеличение скорости загрузки (за счет снижения roadTime тк мы сокращаем расстояние между сервером и клиентом)
  3. Отсутствие на домене хранилища CDN каких-либо Cookies (размер запроса уменьшается).

Браузерный кеш

Жесткое кеширование (200 cache)





Для жесткого кеширования  достаточно добавить заголовки Expires и Cache-Control: max-age.

Для статических компонентов применяется часто правило "без срока давности", устанавливая заголовок Expires (срок жизни кеша) далеко вперед.

Или же наоборот если мы не хотим кешировать страницу то стоит установить в Expires прошедшую дату.


Для динамических компонентов используется соответствующий метатег управления кешированием (Cache-Control), чтобы браузер знал с какой периодичностью проверять содержимое страницы.

Есть еще один мета-тэг Pragma: no-cache довольно хорошо поддерживаемое соглашение, которому следует большинство web-браузеров. Обнаружив этот тэг, они обычно не кэшируют страницу (хотя никаких гарантий нет, это всего лишь соглашение).


Получив такие заголовки, браузер жестко закеширует документ надолго. Все дальнейшие обращения к документу будут напрямую обслуживаться из кеша браузера, без обращения к серверу. Это самый быстрый способ, потому что никакого запроса на веб-сервере не выполняется.

Простое кеширование - HTTP Last-Modified, ETag (304)


Большинство серверов автоматически прописывают этот заголовок при отдаче статических ресурсов. Это позволяет браузеру закачивать новое содержимое только в том случае, если файл реально был изменен. Для этого вместе с запросом GET браузер шлет заголовок:

If-Modified-Since: data,time

Сервер отвечает кодом статуса 304 (not modified/not match) и загружает страницу из кеша в следующих случаях:
  • Если браузер послал заголовок "If-Modified-Since: date", в котором date больше либо равна значению заголовка ответа "Last-Modified: date". Т.е. клиент спрашивает: "Есть ли новая версия с момента date? Если нет, верни мне 304 и сэкономь трафик. Если есть, отдай мне тело страницы".
  • Если браузер послал заголовок "If-None-Match: hash", где hash совпадает со значением заголовка ответа "ETag: hash". Т.е. клиент спрашивает: "Отличается ли текущая версия страницы от той, что я запросил в прошлый раз? Если нет, верни мне 304 и сэкономь трафик. Если да, отдай тело страницы".
Отличие в том что в etag нет привязки ко времени и в хеше мы можем передавать все что угодно. 
Срок жизни браузерного кеша - сессия (до тех пор пока браузер не перезапустить)




304 это не так быстро, как 200 (cache), тк запрос все равно передается на веб-сервер, но сервер не должен отправить содержимое файла.



понедельник, 6 мая 2013 г.

Capistrano

Capistrano — это Open Source-ный инструмент для выполнения скриптов на нескольких серверах, который в основном используется для web приложений. Он позволяет автоматизировать процесс развертывания новой версии на одном или нескольких web серверах и включает поддержку таких задач, как например изменение базы данных.
Capistrano написан на Ruby и является «модулем» фреймворка Ruby on Rails.

Итак, допустим на нашем локальном компьютере  находится приложение(папка с файлами). У этого приложения есть git репозиторий на гитхабе с актуальным кодом. Также у нас есть хостинг  с ssh доступом, куда мы собираемся залить наши файлы. Мы не хотим постоянно возиться с ftp клиентом и решили потратить несколько часов для того, чтобы разобраться в деплойере capistrano.


Капификация


Первое что мы должны сделать после установки capistrano это «capify-нуть» наше приложение. «Капификация» — это процесс конфигурации capistrano для развертывания приложения. Он достаточно прост: убедитесь что вы находитесь в корневой директории вашего проекта и введите

  $ cd /path/deploy/from
  $ capify .

Эта команда создаст два файла:
Capfile — главный файл который нужен capistrano. Capistrano по умолчанию ищет и исполняет «Capfile». Изначально генерируемый Capfile очень прост: все что он делает — загружает «config/deploy.rb»
config/deploy.rb — файл в котором содержатся «настройки» приложения (рецепт)


Структура директорий Capistrano


Проект успешно развернутый с Capistrano будет иметь структуру похожую на приведенную ниже ( где [deploy_to] — это каталог куда мы хотим развернуть проект):

    [deploy_to]
    [deploy_to]/releases
    [deploy_to]/releases/20080819001122
    [deploy_to]/releases/...
    [deploy_to]/shared
    [deploy_to]/shared/log
    [deploy_to]/shared/pids
    [deploy_to]/shared/system
    [deploy_to]/current -> [deploy_to]/releases/20100819001122

Каждый раз когда вы будете разворачивать проект в папке «releases» будет создаваться новая директория, в которую будет копироваться его последняя версия. После этого символическая ссылка «current» обновиться и будет указывать на новую директорию. 


Multistage


В разработке также можно использовать расширение capistrano-ext, которое позволяет делать так называемый multistage. Предположим у вас есть тестовый и рабочий сервера. Вы можете написать отдельный конфиг для каждого из них и выполнять deploy только для нужного сервера.
Создаем свои рецепты: например production.rb и staging.rb. Всё что нам нужно для конфигурации — это написать в файл config/deploy.rb две строки:

    set :stages, %w(staging production)
    require 'capistrano/ext/multistage'

Теперь вы можете выполнять деплой с помощью команд «cap production deploy» и «cap staging deploy». 

Хорошая статья в догонку http://wiki.agiledev.ru/doku.php?id=automation:build_package_deploy


среда, 27 марта 2013 г.

Parralel_tests

Тесты, просто чудесная вещь, но как и многое чудесное имеет свои недостатки. Главный из них – они очень долго выполняются. 


Parralel_tests

parallel_tests – инструмент, позволяющий распараллелить выполнение тестов (test unit), спек (rspec) или фич (cucumber). Надо понимать, что он запускает параллельно разные файлы, но не отдельные тесты внутри одного файла. Поэтому ускорить выполнение одного большого спека вам не удастся.
Всё, что вам нужно делать, это создать БД как сказано в README, а также после каждой миграции делать rake parralel:prepare.
Запускать можно как с параметрами по-умолчанию rake parallel:spec (в этом случае количество процессов определится автоматически по числу ядер), так и указав количество процессов и путь: rake parallel:spec[4,models].
parralel_test для Rspec запускаются командой parallel_spec или bundle exec parallel_spec (т.е. +30 секунд экономии по сравнению с rake).
Если используете parralel_test, то оптимальным числом процессов является значение по-умолчанию (т.е. число ядер)
При выполнении одного теста, т.е. в рядовой работе, parralel_test не даст выигрыша вообще
Есть одно немаловажное НО
Он не будет работать на Windows.
Опирается на DeepTest, который в свою очередь использует  Kernel.fork () ..., который не реализован на Windows.

среда, 27 февраля 2013 г.

Drag and drop - selenium ruby rspec!

Итак спустя 2 дня таки вышло реализовать drag and drop.
Моя конфигурация - webdriver 2.30.0 , ff 18.0.2

И собственно сам кодище))
Причем оба варианта работают, а вот без слипов беда - приходится их везде дописывать
Остальной код не стала подчищать ибо может тоже пригодиться))


# encoding: utf-8
require_relative '../lib/login_page'


describe "Draga" do
  before (:all) do
    @page = LoginPage.new(@browser, true)
    @page.login_user
  end
  it "do it" do
    @page.navigate_to("http://dfghh.test-pul.ru/articles/order")
    element1=@browser.find_element(:css, 'div.tip')
    element2= @browser.find_element(:xpath, '//div[text()="sdfsf"]')
    element3=@browser.find_element(:link,"Отменить")
    el= @browser.find_element(:xpath, '//span[text()="Оформление сайта"]')
    puts el.location
    @browser.mouse.move_to(el)
    sleep 3
    puts element1.location
    puts element2.location
    @browser.action.click_and_hold(element1).move_to(element2).release.perform
    sleep 3
    @browser.action.drag_and_drop(element1, element2).perform

    sleep 3
    #@browser.mouse.click(element3)
    @browser.action.click(element3).perform

    sleep 3
    @page.current_url.should_not include "order"
    sleep 3
  end
end 

вторник, 19 февраля 2013 г.

Причесываю тесты следуя правил


1. Дублирующиеся тесты в разных контекстах можно вынести в shared_examples (https://www.relishapp.com/rspec/rspec-core/v/2-12/docs/example-groups/shared-examples!), например так:
shared_examples_for "страница с ошибками во всех полях" do
  it { @login_page.should be_errors }
  it { @login_page.should be_error_wrong_fio }
  it { @login_page.should be_error_wrong_email }
  it { @login_page.should be_error_no_match_pass }
end
describe " фио цифрами" do
  it { ... }
  it_behaves_like "страница с ошибками во всех полях"
end
describe " фио на английском" do
  it { ... }
  it_behaves_like "страница с ошибками во всех полях"
end
shared_examples лучше все выносить в отдельный файлик и хранить его в папочке support
Если эти описания нельзя как-то логически объединить в один shared_examples_for, навроде "

регистрация с ошибками", то лучше использовать для каждого дискрайба отдельные, пусть даже повторяющиеся, но понятные it

2. в rspec принято все общие заголовочные вещи выносить в spec/spec_helper.rb и во всех спеках:
require 'spec_helper'
кроме того в нем можно предварительно установить общие для тестов переменные
RSpec.configure do |config|
  config.let!(:browser) { Selenium::WebDriver.for :ff }
end

среда, 23 января 2013 г.

Немного о githube


Удалённые репозитории — это модификации проекта, которые хранятся в интернете или ещё где-то в сети. Их может быть несколько, каждый из которых, как правило, доступен для вас либо только на чтение, либо на чтение и запись. Совместная работа включает в себя управление удалёнными репозиториями и помещение (push) и получение (pull) данных в и из них тогда, когда нужно обменяться результатами работы.

1) Есть "главный" репозиторий.  Как правило, в этом репозитории есть несколько веток. доступ к главному репозиторию по ключу, нужен аккаунт на гитхабе, в котором прописан ключ
https://github.com/abak-press/selenium_blizko

2) Каждый разработчик может создавать собственные ветки. Но чтобы не загаживать ими основной репозиторий, каждый из разработчиков должен работать в пределах собственного репозитория. Что значит "форкнуть" проект на гитхабе? Это значит создать полную копию репозитория. Что ж, форкнем его и получим еще один удаленный репозиторий :
https://github.com/grebenschikova/selenium_blizko


3) В гитхабе мы не можем запушить свои изменения в "главный" репозиторий, а можем лишь сделать пулл-реквест. Если он будет одобрен, ваши коммиты будут применены. Для этого и нужно иметь удаленную копию. Ведь иначе можно было создать у себя на машине локальную копию "главного" репозитория, делать изменения, да пушить их.

4) Вот мы и форкнули весь проект. Теперь нам нужно заиметь его на собственном компьютере. Сейчас будет создан еще один репозиторий (уже третий). Этот репозиторий будет условно "локальным". Для этого клонируем его себе на локальную машину из своего репозитория на гитхабе

git clone git@github.com:grebenschikova/selenium_blizko.git

Чтобы просмотреть, какие удалённые серверы у вас уже настроены, следует выполнить команду git remote. Она перечисляет список имён-сокращений для всех уже указанных репозиториев. Если вы склонировали ваш репозиторий, у вас должен отобразиться, по крайней мере, origin — это имя по умолчанию, которое Git присваивает серверу, с которого вы склонировали.

$ git remote
originЧтобы посмотреть, какому URL соответствует сокращённое имя в Git, можно указать команде  опцию -v:
$ git remote -v
origin  git@github.com:grebenschikova/selenium_blizko.git

Если у вас больше одного удалённого репозитория, команда покажет их все. 
$ git remote -v
origin  git@github.com:grebenschikova/selenium_blizko.git
upstream     git://github.com/abak-press/selenium_blizko.git

Это означает, что мы легко можем получить изменения от любого из этих пользователей. Но, заметьте, что origin — это единственный удалённый сервер прописанный как SSH-ссылка, поэтому он единственный, в который я могу помещать свои изменения
Чтобы добавить новый удалённый Git-репозиторий под именем-сокращением, к которому будет проще обращаться, выполните git remote add [сокращение] [url].

git remote add  upstream git://github.com/abak-press/selenium_blizko.git

Этой командой мы сказали "сделай у нашего текущего репозитория ссылку на удаленный репозиторий и для удобства дай этой ссылке понятное имя upstream . Теперь мы всегда будем знать что upstream   это ссылка на наш удаленный репозиторий.

Теперь вы можете использовать в командной строке имена origin и upstream вместо полного URL. Например, если вы хотите извлечь (fetch) всю информацию, которая есть в репозитории, но нет в вашем, вы можете выполнить git fetch upstream
Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. 
Ветка master глобального репозитория теперь доступна локально как upstream/master. Вы можете слить (merge) её в одну из своих веток
Вы можете использовать команду git pull. Она  как правило, извлекает (fetch) данные с сервера, с которого вы изначально склонировали, и автоматически пытается слить (merge) их с кодом, над которым вы в данный момент работаете.

Для переименования ссылок в новых версиях Git'а можно вылолнить git remote rename, это изменит сокращённое имя, используемое для удалённого репозитория. Например, если вы хотите переименовать pb в paul, вы можете сделать это следующим образом:
$ git remote rename pb paul

5) Создаёте новую ветку в своем локальном репозитории (в форке наследуются ветки родителя, так что если форкаете то ветку можно не создавать - master уже будет)
git checkout -b feature


Чтобы посмотреть существующие ветки, введем:
git branch

6) Работаете, делаете коммиты, в случае необходимости отслеживания изменений в «родителе», сливаете изменения с него и вливаете в свою ветку таким образом:
git fetch upstream
git pull upstream master
git merge master

7) Когда работу сделали, заливаете изменения в свой github-репозиторий в свою ветку:
git add .

git commit
git push origin 

8) Теперь идёте на гитхаб, в свой репозиторий и жмёте вверху кнопочку «Pull request»

9) Слева выбираете в какую ветку будут вливаться изменения в родительском репозитории, справа — какие изменения будут браться с вашего репозитория. По примеру: справа abak-press/master, слева grebenschikova/master.

ВАЖНО: Договоритесь с владельцем «родительского» репозитория, в какую ветку будете вливать изменения (он может написать это в README)

10) Заполняете название и описание (название потом попадёт в описание мёрдж-коммита и станет достоянием общественности, учтите это).

11) Нажимаете Send Pull Request

Вуаля, вы его отправили. Владелец рассмотрит ваши изменения и, возможно, их примет и вольёт к себе.
На практике, лучше перед посылкой пулл-реквестов, вручную синхронизироваться с веткой, в которую будете посылать изменения, чтобы у владельца merge прошёл гладко (больше шансов, что пулл примут)
Не забудьте потом сделать git pull upstream master, чтобы увидеть изменения у себя.



Дописать - что делать после принятия пулреквеста.