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

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

# 環境
・macOS High Sierra
・Locust 0.8
・Python 2.7.10
・VisualStudio for Mac Community 7.3.3
・.NetCore 2.1.4

# テスト用サイトの作成
１）.NetCoreのコマンドでテンプレートプロジェクトを作成します

```shell
mkdir Dummy
cd Dummy/
dotnet new mvc
```

２）アップロード処理を書きます。
まずはAboutファイルを書き換えてしまいます。

```html: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>
```
<img width="266" alt="スクリーンショット 2018-05-03 14.48.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/15028/01916a8c-8ead-0e79-a552-a64aeca5094d.png">

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

```C#:/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");
}
```

４）あとはwwwroot配下にuploadsフォルダを作成してあげます。
このフォルダにファイルがアップされていきます。

# locustのコード
locust側のアップロードするフォルダ構成はこんな感じにしました。
<img width="453" alt="スクリーンショット 2018-05-03 14.54.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/15028/b26b8dfd-9c40-bdb1-829e-60eb9d1b7f02.png">

コードは以下のようにするとファイルをアップしてくれます。
/Home/UploadFileというパスはファイルアップロードのSubmitで呼ばれるパスです。

```python: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ファイルのあるパスで以下のコマンド叩きます。

```shell
locust -H http://localhost:57786
```
あとは以下のサイトにアクセスすれば負荷テスト開始です
http://localhost:8089/
<img width="250" alt="スクリーンショット 2018-05-03 15.01.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/15028/8c123a08-fcad-33b0-7a87-3f13e4a047f3.png">

# 結果
![Vue.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/7acae869-d45a-0203-61c4-a4a021bf24ad.gif)

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