funkload-friendlyというモジュールを作りました

FunkLoadPythonで作られたWebアプリケーション向けの負荷試験ツールです。
レポートがわかりやすいので、負荷試験の際によく利用してます。
便利ではあるのですが、いくつか使いづらい点があったので、funkload-friendlyというラッパーモジュールを作りました。
GitHub - tokibito/funkload-friendly: Friendly wrapper of FunkLoad.
Python 2.7のみ対応です(FunkLoadがPython3に未対応)

FunkLoadとの違い

大雑把ですが以下、funkload-friendlyで便利にしたところです。

  • リクエスト間でCookieが保持される(セッションやCSRF対策されたフォームの扱いなどが簡単)
  • REST API(JSON)の扱いが簡単
  • 結果ファイルの出力先にディレクトリを指定できる

なるべくFunkLoadの使用感を崩さないようにしてます。

インストール

virtualenvでどうぞ。
FunkLoadはバージョン1.17.1だとpipでインストールできないので、easy_installでインストールします。
funkload-friendlyはpipでインストールできます。

(venv)$ easy_install funkload
(venv)$ pip install funkload-friendly

使い方

ドキュメントは英語ですがあります。
funkload-friendly — funkload-friendly 0.2 documentation
http://localhost:8000/ で動いているDjangoアプリケーションに向けてテストするとします。
設定ファイルは以下のような感じに書けます。FunkLoadとの差は、指定できる項目が少し増えてるぐらい。
funkload.conf:

[main]
title = My Project Loadtest
description = load testing for myproject
url = http://localhost:8000

[ftest]
log_to = console file
log_directory = ./
result_directory = ./
sleep_time_min = 0
sleep_time_max = 0

[bench]
cycles = 1:3:10
duration = 10
startup_delay = 0.01
sleep_time = 0.01
cycle_time = 1
sleep_time_min = 0
sleep_time_max = 0.5
log_to = console file
log_directory = ./
result_directory = ./

負荷試験のコードは、funkload_friendly.test.TestCaseを継承して書きます。
ログインやAPI呼び出しの検証は、FunkLoadをそのまま使うより簡単に書けます。
loadtest.py:

from funkload_friendly.test import TestCase, description
from funkload_friendly.datatypes import JSONData


class MainTest(TestCase):
    @description("Load top_page")
    def test_top_page(self):
        self.get(self.site_url + "/")


class LoginTest(TestCase):
    def setUp(self):
        # login
        self.get(self.site_url + "/login/")
        self.post(self.site_url + "/login/",
            params=[
                ['username', 'spam'],
                ['password', 'P@ssw0rd'],
                ['csrfmiddlewaretoken', self.cookie['csrftoken']],
            ]
        )

    @description("Load secret_page with login")
    def test_secret_page(self):
        response = self.get(self.site_url + "/secret_page")
        self.assertEqual(response.code, 200)


class APITest(TestCase):
    @description("Load REST API")
    def test_calculate_add(self):
        response = self.post(self.site_url + "/calculate/add/",
            params=JSONData({
                'value1': 100,
                'value2': 50,
            })
        )
        self.assertEqual(response.code, 200)
        self.assertEqual(response.data['result'], 150)

試験の実行は、FunkLoadのコマンドをそのまま使います。

$ fl-run-bench --config=funkload.conf loadtest MainTest.test_top_page

プロジェクトはcookiecutterを使って作成することもできます。
GitHub - tokibito/cookiecutter-funkload-friendly: Cookiecutter template for a funkload-friendly project.

サンプルコード

funkload-friendlyを使った負荷試験のコードと、試験対象のDjangoのプロジェクトをGithubに置いています。
GitHub - tokibito/funkload-friendly-example: Example code for funkload-friendly