Edited at

負荷テストでファイルアップロードしたい

More than 1 year has passed since last update.

Locustでファイルアップロードの負荷テストをしようとして、アップロードのコードがうまく動作せずつまづいたのでメモしておきます。

LocustはPythonでテストケースがかけてフリーで使いやすい負荷テストツールです。


環境

・macOS High Sierra

・Locust 0.8

・Python 2.7.10

・VisualStudio for Mac Community 7.3.3

・.NetCore 2.1.4


テスト用サイトの作成

1).NetCoreのコマンドでテンプレートプロジェクトを作成します

mkdir Dummy

cd Dummy/
dotnet new mvc

2)アップロード処理を書きます。

まずはAboutファイルを書き換えてしまいます。


Views/Home/About.cshtml

@{

ViewData["Title"] = "Upload";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<form method="post" enctype="multipart/form-data" asp-controller="Home" asp-action="UploadFile">
<div class="form-group">
<div class="col-md-10">
<p>ファイル名:
<input type="text" name="fileName" id="fileName" />
</p>
</div>
<div class="col-md-10">
<p>アップロードするファイルを選択してください。</p>
<input type="file" name="files" id="name" multiple />
</div>
</div>

<div class="form-group">
<div class="col-md-10">
<input type="submit" value="ファイルアップする" />
</div>
</div>
</form>


スクリーンショット 2018-05-03 14.48.02.png

3)コントローラーには以下の処理を追加します


/Controllers/HomeController.cs

・・・・ コード省略 ・・・・

private readonly IHostingEnvironment _hostingEnvironment;
// コンストラクタ追加
public HomeController(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}

・・・・ コード省略 ・・・・

[HttpPost]
public async Task<IActionResult> UploadFile(List<IFormFile> files, string fileName)
{
// Webrootパスを取得する
var webRootPath = _hostingEnvironment.WebRootPath;

foreach (var file in files)
{
var filePath = $"{webRootPath}/uploads/{fileName}";
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
return Redirect("About");
}


4)あとはwwwroot配下にuploadsフォルダを作成してあげます。

このフォルダにファイルがアップされていきます。


locustのコード

locust側のアップロードするフォルダ構成はこんな感じにしました。

スクリーンショット 2018-05-03 14.54.11.png

コードは以下のようにするとファイルをアップしてくれます。

/Home/UploadFileというパスはファイルアップロードのSubmitで呼ばれるパスです。


locustfile.py

# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import unicode_literals
from locust import HttpLocust, TaskSet, task

import os.path
import random
import datetime

# アップロード元パス
upload_file_path = os.path.dirname(os.path.abspath(__file__)) + "/UploadFiles/Illust/"
upload_files = ["texture.png", "unitychan.jpg", "wankoro.png"]

class UserTaskSet(TaskSet):
def on_start(self):
"""
タスクセットの開始時に1回のみ呼ばれます。
"""

@task
def upload_task(self):
# 複数のファイルをランダムでアップロード
self.upload(upload_file_path, upload_files[random.randrange(3)])

def upload(self, file_path, file_name):
# アップロードページへ移動
self.client.get("/Home/Upload")

# Content-Type識別
file, ext = os.path.splitext(file_name)
content_type = ""

if(ext == ".jpg" or ext == ".jpeg"):
content_type = "image/jpg"
elif(ext == ".png"):
content_type = "image/png"

# 日付を取得
dt_now = datetime.datetime.now()
timestamp = dt_now.strftime('%Y%m%d%H%M%S')

with open(file_path + file_name, 'rb') as upload_file:

self.client.post("/Home/UploadFile", \
data = { \
'fileName': timestamp + ext, \
}, \
files = { \
'files': (upload_file.name, upload_file, content_type), \
}, \
)

class WebsiteUser(HttpLocust):
task_set = UserTaskSet
# task実行の最短待ち時間
min_wait = 1000
# task実行の最大待ち時間
max_wait = 1000



実行

今回は、テスト用のサイトを実行すると57786ポートで動作していました。

locustfile.pyファイルのあるパスで以下のコマンド叩きます。

locust -H http://localhost:57786

あとは以下のサイトにアクセスすれば負荷テスト開始です

http://localhost:8089/

スクリーンショット 2018-05-03 15.01.50.png


結果

Vue.gif

これでポコポコとファイルアップロード処理がされるようになりました!