2013-07-30

IntelliJ Idea и автоматизация конвертации SCSS в CSS, а CSS в minify-версию

Для того, чтобы автоматизировать работу с определёнными категориями файлов, нужно установить плагин File Watchers. В нём есть несколько предустановленных механизмов, однако они требуют для своей работы сторонние скрипты. Например, чтобы автоматически конвертировать SCSS-файлы в CSS, нужно установить ruby-gem sass, а для сжатия CSS и JS нужен компрессор. В Ubuntu это всё можно сделать одной командой bash:

sudo apt-get install ruby-sass yui-compressor

Настройка File Watcher выглядит тривиально. Вот так:

2013-07-29

Неожиданное применение автоматического тестирования

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

Когда форма была исправлена, встал вопрос: что делать? Вопрос "Кто виноват", понятное дело, не стоял. Исправление можно было произвести двумя путями: один - это писать скрипт, учитывающий все условия формы и прогонять сохранённые данные через него. Можно, но времени разбираться на этот момент не было (форма всё-таки и правда не тривиальная была). Второй способ - это заставить пользователей снова открывать форму для редактирования и пересохранить данные, т.е. просто открыть страницу с определённым URL и нажать кнопку "Сохранить". Конечно, они в этом не виноваты, и страдать не должны. Делать это мне? Ещё дольше, чем скрипт писать!

А почему бы не поручить это кому-нибудь, у кого много свободного времени, кто не будет возражать и способен делать рутинную работу без всякого ропота? Среди людей таких нет. Тогда обратимся к роботам.

Ну и тут, как вы догадались, Selenium спешит на помощь. Буквально несколько минут, и готов тестовый скрипт, который займётся всей работой. Запускаем Selenium server ...


java -jar selenium-server-standalone-2.33.0.jar

... и наш скрипт ...


python test.py

... и наблюдаем, как человек-невидимка открывает браузер, переходит по ссылкам и нажимает кнопки. Что нам и нужно было.

А вот, собственно, скрипт.


#!/usr/bin/env python
#coding:utf8

from selenium import webdriver
import unittest
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

class Wd(unittest.TestCase):
 def setUp(self):
  self.driver = webdriver.Remote(
   command_executor='http://0.0.0.0:4444/wd/hub',
   desired_capabilities=DesiredCapabilities.FIREFOX)
  self.driver.implicitly_wait(30)
  self.base_url = "http://my.address.ru"

 def test_saveButtonClick(self):
  driver = self.driver
  for id in [222706,426061,441101]:
   url = "%s/edit_page_%d" % (self.base_url,id)
   driver.get(url)
   driver.find_element_by_id("saveform").click()

 def tearDown(self):
  self.driver.quit()

if __name__ == "__main__":
 unittest.main()

2013-07-22

Использование оператора for в Twig: итератор

Некоторое время пользуюсь шаблонизатором Twig, где циклы в шаблонах задаются практически только с использованием оператора for:

{% for item in some_array %}
 {{ item }}
{% endfor %}

При обходе массива (что и делается в большинстве случаев) вопросов не возникало. Но тут приспичило мне сделать цикл типа while. То есть подразумевалось нечто вроде

{% while item = some_array.next() %}
 {{ item }}
{% endwhile %}
однако, while не реализован в Twig.

Недолгий гуглёж привёл меня (внезапно!) на страницу документации Twig, где черным по английскому написано: "A sequence can be either an array or an object implementing the Traversable interface." Итак, решается задачка таким образом: создаётся объект, имплементирующий методы стандартного PHP-интерфейса Iterator, подаётся в оператор for и всё работает. Как-то так:


class SomeItems implements Iterator{
 private $position = 0;
 private $items = [];

 public function add($item){
  $this->items[] = $item;
 }

 public function current() {
  return $this->items[$this->position];
 }
 public function key() {
  return $this->position;
 }
 public function valid() {
  return isset($this->items[$this->position]);
 }
 public function rewind() {
  $this->position = 0;
 }
 public function next(){
  ++$this->position;
 }
}

$items = new SomeItems();
$items->add('One');
$items->add('Two');
$twig->display('page.twig', ['items'=>$items]);

На странице page.twig используем обычную конструкцию:

{% for item in items %}
 {{ item }}
{% endfor %}
В результате на странице выведены слова "One" и "Two".

2013-05-15

IntelliJ Idea + Solarized Color Schemes

Стал пользоваться IntelliJ Idea для всех проектов. Совершенно невероятно продуманная IDE, но речь не об этом. Захотелось сразу же прикрутить туда популярные цветовые схемы Solarized, к которым я уже привык. Делается это несложно. А именно:
cd ~/.IntelliJIdea12/config/colors/
wget https://raw.github.com/altercation/solarized/master/intellij-colors-solarized/Solarized%20Dark.xml
wget https://raw.github.com/altercation/solarized/master/intellij-colors-solarized/Solarized%20Light.xml
Заускаем Idea, в настройках находим список цветовых схем, а в них - Solarized Dark и Light.

2013-04-28

Нафаршированный ffmpeg : готовый deb-пакет и немного записи

Примерно год назад я писал о том, как установить ffmpeg со всевозможными кодеками в Ubuntu 12.04. Это работает и в 13.04, без изменений. Но, так как я люблю моих читателей, и предполагаю, что им лень собирать это самостоятельно, предлагаю скачать уже собранный под 32-битную версию Ubuntu 13.04 пакет.
Вот ссылка.

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

P.S. Кстати, а вы знали, что с помощью ffmpeg можно записывать то, что слушаете, к примеру в интернете? Например, с Яндекс.Музыки. Я раньше писал о том, как это сделать, так вот что касается pavucontrol - обязательно, а вместо заморочек с audacity можно сделать так:

ffmpeg -f alsa -ac 2 -i pulse -acodec libmp3lame -aq 4 file.mp3

Это даст нам файл mp3 с переменным битрейтом 140-185 (-aq 4). О том, какие битрейты можно выставить, прочтите здесь. Самое сложное - вовремя включить и выключить запись. Я пробовал записывать подряд, и потом разбить трек на части с помощью mp3splt по секунде тишины, но 1) возникают артефакты в месте разрыва и 2) иногда в композициях бывает тишина, так надо. Вобщем, пока думаю, как бы это автоматизировать, а вы присоединяйтесь!