Симплог — простые блоги

03

Очередной безупречный день

Как захватить мир, пособие для начинающих

Не так давно, после обновления Firefox перестал работать мой любимый It’s all text плагин, который позволял редактировать содержимое форм на сайтах в любом редакторе.

На замену нашелся Ghost Text, который, увы, тоже пока не совместим с новым FF, но хотя бы есть для Хрома.

Чтобы редактировать с его помощью формы в GVim, надо не только поставить расширение для браузера, но и запустить небольшой скрипт на локальной машине:

https://github.com/falstro/ghost-text-vim

После скачивания файла ghost-text-server.tcl лучше положить его куда-нибудь, где у вас лежат исполняемые файлы конкретного юзера, например, ~/bin.

Для запуска tcl-скриптов установите нужные пакеты:

sudo aptitude install tcl tcllib

Добавить комментарий

Этот пост будет посвящён картинкам профиля, фотографиям пользователей, юзерпикам, аватаркам или как их кто только не называет.

Довольно давно, наверное, когда только появилась возможность загружать на сайты картинки, разработчики решили, что здорово, когда пользователь видит на своей странице, собственно, себя или какое-то изображение, которое он с собой ассоциирует. И с ними трудно не согласится, действительно здорово!

Так появились аватарки. Если мне не изменяет память, основное применение было ЖЖ и всевозможные форумы. В то же время возникла и проблема: что делать, если пользователь ничего не загрузил? Дальше по-порядку от простого к сложному.

Обязательная картинка

Не давать пользователю регистрироваться без картинки — довольно странное, но по-моему до сих пор встречающееся решение. Очевидно плохое. Таким образом можно здорово урезать конверсию посетителей в регистрации — не у каждого найдётся на компе подходящая фотка. Если же пользователю надо зарегистрироваться — он пихнёт в форму какой-нибудь шлак и сервис будет выглядеть как помойка: жёлтые уточки, фотки облаков с заставки windows и т.д.

Не отображать картинку в профиле

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

Заглушка: «Мистер Никто»

Знакомьтесь, таинственный незнакомец.

Нет, это точно самое популярное решение. Этот парень — красная тряпка для феминисток, он вездесущ и повсеместен, хоть и принимает разные обличия. Бойтесь его, ибо он вечно следит за вами своими ненарисованными глазами.

Фактически, вместо изображения пользователя выводится информация о том, что изображения нет. Если призадуматься, то это ужасное решение — все пользователи, не загрузившие картинку профиля, а таких всегда большинство, выглядят одинаково, серо, уныло и, по задумке, никак. В большинстве переписок пользователь не отличит себя от собеседника — его картинка такая же.

Для каждого, кто берёт таких человечков из поиска по картинкам гугла и использует в качестве заглушки на своём сайте, в аду уже подготовили отдельный котёл. Если вы выбрали это решение, хотя нарисуйте/закажите себе что-то оригинальное, как это сделали, например, разработчики «Вконтакте»:

Удалённый пользователь VK.com

Идентиконы или identicons

Когда все поняли, что вышеупомянутый мистеримэн — приспешник сатаны и несёт в мир уныние, Don Park придумал Identicons (цель была немного иная, аналогичная QR-кодам, но не суть). Идентиконы — это крутая штука: это картинка, которая автоматически генерируется на основе любого текста с помощь хитрого алгоритма.

Мой идентикон

Вот так, например, выглядит идентикон для Вадима Венедиктова. Можете поиграться и посмотреть, какая картинка соответствует вашему имени, фамилии, нику.

Индентиконы сейчас набирают популярность (в основном в среде программистов) и начинают активно бороться с серенькими человечками. Из самых популярных примеров Wordpress и наш любимый StackOverflow.

Генерируемые роботы

Идентиконы всё-таки тоже не слишком весёлые. После их внедрения сайт становится утыканным бессмысленными орнаментами и походит больше на турецкий базар, чем на социальный сервис. Поэтому, например, github решил вместо этих орнаментов генерировать изображения пользователей в виде простеньких пиксельных роботов.

Вот так выглядит мой, почему-то тоже розовый:

installero identicon on github

Есть ещё сайт Robohash.org. Там я выгляжу вот так:

installero identicon on robohash

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

Картинка с буквой

С приходом флэта эта тема стала чертовски популярной. Её используют, например gmail и mail.ru:

Gmail interface.

Очень классное решение, кстати. Во-первых, всё ещё понятно, что пользователь не загрузил для себя никакой картинки, во-вторых, вы ни за что не перепутаете письма от разных контактов и при этом нет непонятных роботов или орнаментов. Если лень заморачиваться, на мой взгляд, самое отличное решение.

Gravatar

Про него здесь я просто не мог не рассказать.

Gravatar

Если вы зарегистрируетесь на Граватаре и загрузите свою фотографию то она будет отображаться на всех сервисах, где разработчики решили не парится с загрузкой собственных картинок для пользователей. На самом деле — это хорошее решение, чтобы вывести что-то, например, рядом с комментарием в каком-нибудь авторском блоге. Ну посудите сами, кто будет загружать картинку, чтобы оставить комментарий в авторском блоге.

Чего бы хотелось мне

Чтобы дефолтная картинка была во-первых, цветной, во-вторых, человекоподобной. Роботы — это здорово, но всё-таки достаточно бездушно. И бог с ним с распознаванием пола. Имеется же в интернете огромное количество сервисов, которые генерируют мультяшных персонажей для использования в аватарках:

Cartoon Avatar

Avachara
Face Your Manga
Pick A Face
Make Avatar
South Park Studios

Есть даже для Андройда. Самая классная, кстати:

U Face

UFace image

Возможно, даже лучше заранее нарисовать несколько картинок и присваивать их произвольно каждому новому пользователю. А захочет загрузить что-то своё — всегда пожалуйста. Именно так, кстати, поступили в Basecamp. Только картинки у них абстрактные.

Basecamp defaul userpics

Добавить комментарий

1. Зарегистрировать новый аккаунт на clodo.ru.

2. Купить, оплатить и включить сервер. Например, минимальный:

Операционная система: Ubuntu 12.04 64bit
Оперативная память: 256MB – 512MB
Процессор: 1 core
Жесткий диск: 5GB
Трафик: 20GB
Операционная система:
Датацентр: KIAEHOUSE

3. Получить рутовый доступ, залить ключи. Публичный IP сервера можно посмотреть в
панели управления clodo. Там же в панели можно посмотреть пароль от рута. Далее считаем, что ваш ip — 3.15.0.0.

ssh-copy-id root@3.15.0.0

Если на вашей машине нет ключа (нет файла ~/.ssh/id_rsa.pub) — создайте его командой

ssh-keygen -t rsa

4. Под рутом установить passenger, mysql, git. Поставить bundler (если у вас в rails-проекте есть Gemfile, в противном случае сами ставьте все gem-ы).

apt-get install python-software-properties
apt-add-repository ppa:brightbox/passenger-nginx
apt-get update
apt-get install nginx-full git mysql-server libmysqld-dev rubygems
gem install bundler

При установке mysql предложат ввести пароль рутового пользователя.

5. Создать в mysql пользователя и базу для нового приложения, дать пользователю права.

mysql -uroot -pmypass
CREATE USER 'my_username'@'localhost' IDENTIFIED BY 'my_password';
CREATE DATABASE `my_database` CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON my_database.* TO 'my_username'@'localhost' IDENTIFIED BY 'my_password';
exit;

6. Под рутом настроить nginx, например, командой vi /etc/nginx/nginx.conf. Этот файл примерно таким и будет по умолчанию. По идее, его можно не трогать.

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;
	gzip_disable "msie6";

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# nginx-naxsi config
	##
	# Uncomment it if you installed nginx-naxsi
	##

	#include /etc/nginx/naxsi_core.rules;

	##
	# nginx-passenger config
	##
	# Uncomment it if you installed nginx-passenger
	##
	
	#passenger_root /usr/lib/phusion-passenger;
	#passenger_ruby /usr/bin/ruby;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

/etc/nginx/conf.d/passenger.conf

passenger_root /usr/lib/phusion-passenger;

Делаем отдельный файл для конфигурации приложения.

/etc/nginx/sites-available/my_site

server { 
	listen   80; 
	passenger_enabled on; 
	server_name www.my_site.com my_site.com; 

	access_log  /var/log/nginx/my_site.access.log; 

	root /home/my_site/www/public; 

	# Redirect from www.my_site.com to my_site.com

	if ($host ~* www\.(.*)) { 
		set $host_without_www $1; 
		rewrite ^(.*)$ http://$host_without_www$1 permanent; 
	}

	# Redirect from various domain names to my_site.com

	if ($host !~* (.*\.)?my_site\.com) { 
		rewrite ^(.*)$ http://my_site.com$1 permanent; 
	} 
}

ln -s /etc/nginx/sites-available/my_site /etc/nginx/sites-enabled/my_site
service nginx restart

7. Создать пользователя my_site с паролем, сделать ему bash оболочкой по умолчанию, залить ключи:

useradd -d /home/my_site -m my_site
passwd my_site
chsh -s /bin/bash my_site

И, вернувшись на свою машину, выполнить

ssh-copy-id my_site@3.15.0.0

8. Залить публичный ключ нового пользователя в deploy-ключи github-а:

ssh my_site@3.15.0.0
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub

Deploy-ключи заливают здесь: https://github.com/my_github_username/my_site/settings/keys.

9. Под новым пользователем залить код в папку www в домашней директории, поставить gem-ы, настроить базу…

git clone git@github.com:my_github_username/my_site.git www
cd www
bundle config path vendor/bundle
bundle install
vi config/database.yml
production:
   adapter: mysql
   encoding: utf8
   host: localhost
   database: my_database
   username: my_username
   password: my_password

Если начинаете жизнь с нуля:

bundle exec rake db:migrate RAILS_ENV=production

или залейте дамп старой базы, если он у вас есть.

10. Настроить всё остальное, что нужно вашему приложению, например

git submodule init && git submodule update

и прочее.

11. Для перезапуска сервера создать файл tmp/restart.txt

mkdir tmp
touch tmp/restart.txt

2 комментария

Вадим Венедиктов, 29 августа 2011 года

Макс написал, как он настраивал шифрование писем для одного из наших проектов:

ActionMailer_X509: подписываем и шифруем письма прямо в Ruby On Rails

1 комментарий

Вадим Венедиктов, 17 июля 2011 года

Отличный простой инструмент для совместной удалённой разработки: piratepad.net

Добавить комментарий

А вот пример довольно странного поведения от отечественных знатоков бизнеса. Это письмо я получил от MBA Consult

Здравствуйте!

Напоминаем, что Вы зарегистрировались на Информационную сессию Harvard Business School.

... *информация о встрече* ...

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

Ни в теме, ни в подписи не указано имени того, кто мне пишет. Письмо, фактически, анонимно. Конечно, я понял, почему оно мне пришло и зачем мне его послали, я бы слова не сказал про этого робота, если бы не одно «но».

Меня просят ответить!

Как только я начал писать ответ, я почувствовал себя глупо. Что мне написать: «Здравствуйте, робот! Приятно, что вы позаботились обо мне и напомнили про сессию…»? Вежливые компании не заставляют своих клиентов чувствовать себя глупо.

Не смотря на то, что это, безусловно, полезное напоминание было сгенерировано автоматически, организаторы могли сделать его более человечным. Роботы не ведут бизнес. В любой компании работают обычные живые люди. Почему не указать имя и фамилию ответственного лица? Например, Вячеслав Давиденко. Всем всё равно будет понятно, что этот Вячеслав не писал около сотни писем вручную. Но лично мне будет приятнее ответить реальному человеку, нежели безликой программе.

3 комментария

Пару месяцев назад на хабре пропиарился сервис Readbox.info. Сервис показался интересным, хотя я так и остался на Яндекс.Подписках. Но вот уже с начала года я, незаметно для себя, полностью мигрировал на Readbox.

Причин много, но вот самые привлекательные для меня возможности Readbox’а:

  • Не требует регистрации, авторизация через OpenID ЖЖ, Яндекс, Google и прочее
  • Выгрузка RSS-ленты в формате fb2 для чтения на электронных книгах офлайн
  • Поддержка полнотекстовых RSS, что особенно удобно при выгрузке на электронную книгу
  • Встроенный в ленту переводчик бывает удобно перевести незнакомое слово
  • Горячие клавиши, частью заимствованные у Google Reader’а
  • Возможность не показывать некоторые ленты в общем списке так я фильтрую github’овские RSS И многое другое

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

Интерфейс Readbox очень удобен, скорость достойная приличная. Учитывая поддержку горячих клавиш ощущаешь себя не хуже чем на настольном приложении. Судя по блогу разработчиков сервис постоянно улучшается. Поддержка на высоте: когда я задал вопрос “как я залогинен в систему”, ответ пришёл мне email’у, а также был продублирован через jabber. Все эти сведения они постарались вытащить из моего Яндексового OpenID, попутно пообещав улучшить интерфейс в этом вопросе. Кстати, фреймворк разработки — Ruby on Rails.

1 комментарий

Вадим Венедиктов, 31 декабря 2010 года

Собираетесь общаться с клиентами, работая в российской компании — научитесь извиняться.

Добавить комментарий

RVM — прекрасный набор скриптов, который позволяет делать удивительную штуки, когда вам нужно использовать разные версии ruby.
Вообще, я давно присматривался к RVM, но отсутствие острой необходимости и отсутвие PKGUILD для ArchLinux останавливали меня. И вот, наконец, у меня дошли руки. Установка оказалась очень проста (я выбрал вариант не общесистемной установки, а на одного пользователя):

bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

А после надо занести в файл ~/.bash_profile или ~/.bashrc следующую строку

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"

Проверить, что установка прошла успешно можно с помощью команды type rvm | head -n1. Ответом будет нечто вроде rvm is a function.

Теперь можно воспользоваться магией rvm. Установка Ruby 1.8.7

rvm install 1.8.7

Переключиться на 1.8.7

rvm 1.8.7

Обратно на системный ruby

rvm system

Причём как только вы переключились на какую-то версию ruby, это значит, что всё, что вам нужно теперь тоже с этой версией ruby: bundler, irb, gem, rake, spork и т.д..

Есть ещё шикарная штука – файлы .rvmrc для проектов. Т.е. вы в проекте прописываете

echo 'rvm ree' > .rvmrc

И у вас по умолчанию при входе в проект используется Ruby Entherprise Edition. А в другом пропишите 1.9.2 и при переходе в его папку у вас будет 1.9.2!

А ещё есть возможность ставить gem’ы наборами и ещё куча всего!

Резюмируя, скажу, что rvm — шикарная штука. И она отлично помогает управляться с двумя нашими проектами, один под 1.8.7, другой под 1.9.2 без лишних сложностей.

Добавить комментарий

[JS Fiddle]

Специально для того, чтобы один разработчик мог быстро показать какой-нибудь кусок кода другому существует Pastie и Gist.

Но периодически, заседая на официальном канале #jquery, я сталкиваюсь с необходимостью показать не только код, который вызывает у меня вопросы, но и создать работающий или, что чаще, неработающий пример. Это можно сделать с помощью JS Fiddle

Редактор HTML + CSS + JS с разметкой синтаксиса и возмжностью подгрузить часто используемые фреймворки (JQuery, Prototype, mootools) позволяет сосредоточиться только на главном: «что, собственно, не работает?».

Добавить комментарий

Теги – замечательный инструмент для упорядочивая сценариев Cucumber’а (или примеров Rspec’а). Вы можете давать теги всему. Вы можете метить долговыполняющиеся сценарии (примеры) тегом slow, и не запускать их в команде по-умолчанию. Вы можете, в случае с кукумбером, метить сценарии (или, кстати, целиком фичу) тегом @javascript, и они будут выполнятся с использованием текущего javascript-драйвера (кстати, эта возможность доступна из коробки).
Но самое часто-используемое – это специальная метка для того, над чем вы работаете именно сейчас. В кукумбер она доступна по-умолчанию и зовётся @wip. Там даже преднастроен специальный профиль, который переключает форматирование на более удобное и запускает только @wip-сценарии:

cucumber -p wip

Впрочем, если вам хочется только фильтровать теги, то можно воспользоваться ключём --tags: cucumber --tags wip. Пометь сценарий тегом wip можно следующим образом

@wip
Scenario: my scenario
  Given ...

Подробнее о тегах в кукумбере можно прочесть в официальной вики.

Отличным дополнение к тегам в кукумбере является возможность создавать перехватчики (hooks). Можно перехватить что угодно, но нас интересует возможность перехватить выполнение сценария с определённым тегом.
Скажем, мы хотим, чтобы у сценариев с тегом @lvh-js параметр Capybara.app_host менялся на http://lvh.me:9887 (lvh.me, а также все его поддомены, ссылаются 127.0.0.1), и включался драйвер selenium. Сделать это очень просто. Для этого создаём файл features/support/lvh-js-tag.rb, и пишем туда следующее:

Before('@lvh-js') do
  Capybara.app_host = "http://lvh.me:9887"
  Capybara.current_driver = :selenium
end

Готово. Подробнее о перехватчиках также можно прочесть в официальной вики.

Что касается rspec’а, то там теги задаются чуть иначе. Теги могут быть представлены как строка, например, wip и как пара ключ-значение, например, speed:slow. Для того, что б пометь it\describe\context.. обычным тегом, надо добавить в в конце вызова :wip => true, если же хочется пометить парой ключ-значение, то :speed => :slow. Например:

it "my current example", :wip => true do
  ...
end

Теперь можно запустить на выполнение примеры только с тегом wip: rspec --tag wip.
Челимский, что кстати очень разумно, переносит документации в фичи кукумбера, поэтому подробнее о тегах в rspec можно прочесть в официальной фиче.

2 комментария

Вадим Венедиктов, 15 ноября 2010 года

Про изменение отношения к конкурентам:

Мы должны применять кардинально другие подходы. Они (конкуреты, прим. моё) вкладывают кучу бабла. Мы — не будем.

petRUShka, 05 августа 2009 г.

Вуху! А таксовик-то уже даже хохлы копируют. Купим их потом ;)

petRUShka, 13 ноября 2010 г.

1 комментарий

  1. Начинается работа следующим образом: в двух вкладках терминала запускается bundle exec spork и bundle exec spork cuc для ускорения с помощью spork’а rspec’а и cucumber’а, соответственно.

  2. Ещё в одной вкладке запускается autotest: bundle exec autotest. Теперь всякое моё изменение тут же тестируется. Кстати, я выставляю AUTOFEATURE=false, т.к. запускать ещё и cucumber по факту изменений кажется мне слишком дорогим удовольствием. Особенно, если он, как у нас в проекте, прогоняется целиком примерно за 5 минут.

  3. Далее, действуем согласно парадигме BDD. Но надо убедиться, что все команды (cucumber, rspec и rspec внутри autotest) запускаются с ключами --drb. Для этого можно, например, погасить оба spork’а и запустить прогон тестов. Если он настроен на использование spork, то в терминал выведется No DRb server is running. Running in local process instead ....

  4. Если какой-нибудь отдельный spec разросся (как у нас) до невероятных размеров, а надо работать именно с ним, то я гашу autotest. И во время работы запускаю только конкретный it. Делается это так: надо выяснить, на какой строчке находится этот it (или context\describe), например, 521, а после запустить rspec только для it’а на 521 строчке: bundle exec rspec -l521 spec/model/my_model_spec.rb

  5. Кстати, если вы работаете с cucumber, то чрезвычайно удобная штука – это теги. По-умолчанию, есть тег @wip (work in progress). Ставите у текущего сценария этот тег и запускаете кукумбер: bundle exec cucumber -p wip. Выполнится прогон только сценариев с тегом @wip.

  6. По окончании работы надо выгрузить всё в общий репозиторий. Предварительно, конечно, надо прогнать все тесты с новым функционалом (в т.ч. с тем, что внесли ваши коллеги). Для этого у нас есть специальный alias: alias jointheranks='git pull && bundle update && rake db:migrate && rake parallel:prepare && bundle exec parallel_spec && bundle exec parallel_cucumber && git push'

2 комментария

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

Spork

Spork – это инструмент, который позволяет не перегружать тестовое окружение (например, сам Rails, rspec и прочие тестовые библиотеки, которые вы используете), всякий раз, как прогоняется тест. Вместо этого вы запускаете spork (для rspec или unit test) или spork cuc (для cucumber), дожидаетесь, пока он подгрузит окружение, и после этого запускаете ваш rspec или cucumber с ключём --drb. И они начинают гонять тесты, минуя стадию подгрузки окружения! С настройкой, вы справитесь очень легко.

Да, для Rails 3 вам понадобится rc-версия spork (на данный момент, 0.9.0.rc2), а cucumber + autotest не работают с spork’ом хотя кто-то утверждает, что всё в порядке.

Parralel_tests

parallel_tests – инструмент, позволяющий распарралелить выполнение тестов (test unit), спек (rspec) или фич (cucumber). Надо понимать, что он запускает параллельно разные файлы, но не отдельные тесты внутри одного файла. Поэтому ускорить выполнение одного большого спека вам не удастся.

Всё, что вам нужно делать, это создать БД как сказано в README, а также после каждой миграции делать rake parralel:prepare.

Запускать можно как с параметрами по-умолчанию rake parallel:spec (в этом случае количество процессов определится автоматически по числу ядер), так и указав количество процессов и путь: rake parallel:spec[4,models].

Я провёл несколько испытаний. Rspec:

$ date && rake spec:controllers && date
Сбт Ноя 13 14:53:38 MSK 2010
Finished in 58.36 seconds
350 examples, 0 failures
Сбт Ноя 13 14:55:33 MSK 2010

Итого, Rspec утверждает, что справился за 58.36 секунд, а по выводу команды date видно, что потребовалось 115. Т.е. ещё 57 секунд (которые, кстати, мог бы сэкономить spork) потребовалось на загрузку окружений. Кстати, на подгрузку окружения для команды rspec spec/contollers или для команды bundle exec rspec spec/contollers тратится около 30 секунд (на bundle на пару секунд дольше).

Посмотрим, на parallel с параметрами по-умолчанию:

$ date && rake rake parallel:spec[controllers] && date
Сбт Ноя 13 14:55:33 MSK 2010
2 processes for 16 specs, ~ 8 specs per process
Finished in 10.39 seconds
184 examples, 0 failures
Finished in 51.1 seconds
166 examples, 0 failures
Results:
166 examples, 0 failures
184 examples, 0 failures
Took 89.216297137 seconds
Сбт Ноя 13 14:57:19 MSK 2010

В первый раз я вывел весь лог, чтобы было понятно, как он выглядит, далее будет короткая выдержка.
Итого: 89.216297137 секунд по словам parralel_test и 106.0 фактических секунд (сэкономлено ~9 секунд). 89 сек – странная цифра, т.к. реальное время выполнения – максимальное из всех процессов, т.е. 51.1, что соответствует экономии в 9 секунд.

$ date && rake rake parallel:spec[4,controllers] && date
Сбт Ноя 13 14:57:19 MSK 2010
4 processes for 16 specs, ~ 4 specs per process
Took 130.743829138 seconds
Сбт Ноя 13 14:59:47 MSK 2010

А вот попытка выполнить на 4_ёх процессах (при реальных 2_ух ядрах) только ухудшила ситуацию: 148.0 – реальных секунд и 130.743829138 заявленных.

Тесты для cucumber:

$ rake cucumber
Сбт Ноя 13 15:26:32 MSK 2010
5m38.088s
Сбт Ноя 13 15:33:09 MSK 2010

Т.е. реальных 6 минут 37 секунд, заявленных 5 минут 38 секунд. Т.е., как и прежде – около минуты на подгрузку окружения.

$ rake parallel:features
Сбт Ноя 13 15:37:28 MSK 2010
Took 268.90437579 seconds
Сбт Ноя 13 15:41:54 MSK 2010

Итого – почти 4 с половиной минуты заявленны, а реальных 4 минуты 50 секунд. Т.е. выигрыш по сравнению с непараллельными тестами 1 минута 47 секунд. Кстати, при прогоне тестов с selenium реально запускаются два сервера и две копии браузера. При этом два сервера могут конфликтовать.

$ rake parallel:features[4]
Сбт Ноя 13 15:41:58 MSK 2010
Took 323.654938436 seconds
Сбт Ноя 13 15:47:39 MSK 2010

Итого на 5:20 заявленных, 5:41 реальных, что всё равно лучше, чем вообще без распарралеливания, но сильно хуже 2 процессов.

К сожалению, spork и parralel_test не работают вместе :(

Итого:

  1. Использование rake spec вместо rspec scec/ или bundle exec rspec увеличивает время выполнения теста ~ на 30 секунд. Кстати, parralel_test для Rspec запускаются командой parallel_spec или bundle exec parallel_spec (т.е. +30 секунд экономии по сравнению с rake).
  2. Если используете parralel_test, то оптимальным числом процессов является значение по-умолчанию (т.е. число ядер)
  3. При выполнении одного теста, т.е. в рядовой работе, parralel_test не даст выигрыша вообще, а spork сэкономит по 30 секунд на прогон.
  4. parralel_test – отличная вещь при прогоне всех тестов перед выгрузкой коммита в общий репозиторий.

P.S. Rails 3 + Ruby 1.9.2 + rspec 2.0.1 + cucumber 0.9.3

2 комментария

Вадим Венедиктов, 5 ноября 2010 года

В принципе, мы здесь играем в игрушки. Но когда на странице сайта появляются логотипы Visa и MasterCard, отношение к нашим игрушкам становится более серьёзным.

Добавить комментарий

 
[IMG]

Вадим Венедиктов

Физик, дизайнер интерфейсов, блоггер, создатель Симплога и Таксовика.