середа, 4 листопада 2009 р.

Автоматичне тестування у bash

Рік тому з’явилася була ідея створювати для автоматичної перевірки всієї системи невеликі скрипти оболонки Unix. Відверто, з нашим лідером QA ми навіть спромоглися втілити її. Після нескладної підготовки середовища, запускався написаний на bash скрипт, який по SSH керував приладом, заставляючи його відіслати якісь повідомлення. Разом із тим виконував якісь перевірки на сервері. Така нехитра схема нам дозволила автоматизувати рутинні перевірки, і зрештою довести до систему до пуття.

Тепер знову постала необхідність розкопувати старі кулемети. Розробляючи нову версію сервера з нуля, ми зіткнулися із дикою бідою. Дуже важко відслідкувати всі внесені до схеми бази даних зміни і вчасно поновлювати код демонів (хто робив, той зрозуміє). Тому тепер я намагаюся пліч-о-пліч із ручними перевірками “занотовувати” свої дії у скрипти bash. Таким чином легко потім повторювати перевірки щодня. Можливо, в майбутньому автоматизуємо нічні збірки із прогонкою всіх тестів.

Такі тести мали б називатися регресійними модульними, але вони не те саме, що модульні тести вихідного коду. Бінарний модуль — це чорна скринька, але перевіряються внутрішності системи (записи в базі даних, зміни у файловій системі тощо).

Запускаються ці диво-скрипти на перевірюваному розгорнутому сервері, але покладаючись на структуру вихідного коду. Типові приклади дій у скриптах такі:

  • Визначаються якісь вихідні значення, параметри:

    
    serial=1234567890
    msg_idx=1234
    cam_cnt=4
    

  • Готується оточення, заводяться значення в базу даних, перезапускаються потрібні демони тощо:

    
    echo "Creating database ipmp"
    mysql << END || die "Failed to recreate the database ipmp"
      DROP DATABASE IF EXISTS ipmp;
      `cat $vdns_root/documents/web/ipmp/Ipmp2.sql`
    END
    
    echo "Preparing environment"
    rm -rf /ha_shared/vdns/eventsPictures
    mysql ipmp << END || die "Failed to prepare environment"
      INSERT INTO unit
      SET utc_id = 1,
          unt_serial = '$serial',
          unt_remote_access = 'allow';
    END
    
    echo "Restarting pnet_server"
    killall -KILL pnet_server
    ($vdns_root/src/apps/pnet_server/pnet_server &)|| \
        die "Couldn't launch pnet_server"
    
    echo "Restarting pnet_notify"
    killall -KILL pnet_notify
    ($vdns_root/src/apps/pnet_notify/pnet_notify &) || \
        die "Couldn't launch pnet_notify"
    sleep 2
    

  • Від імені приладу відсилається запит:

    
    # Sending error request
    resp=`curl -s -d asdf "http://localhost:8080/scripts/notify.php"`
    [[ $? -eq 0 ]] || die "Failed to get error response"
    [[ "$resp" =~ "<index>-1</index>" ]] || die "Incorrect error response"
    
    # Sending request
    ./send1.sh -a localhost -s $serial -i $msg_idx -c $cam_cnt
    [[ $? -eq 0 ]] || die "Failed to send the event"
    

  • Нарешті, виконуються перевірки ефекту запиту:

    
    echo "Checking events"
    res=`mysql -s ipmp <<END
      SELECT etv_id,
             evt_description,
             evt_message_index,
             evt_original_device_name
      FROM event;
    END` || die "Failed to check events"
    
    diff -uw <(echo "$res") <(cat <<END
    31      Fire    $msg_idx        Control Panel
    END)
    
    [[ $? -eq 0 ]] || die "Event don't match"
    

Для порівняння табличних даних в нагоді дуже стає команда diff: виходить компактно, інформативно. Краса!

Немає коментарів:

Дописати коментар