Azure Functionsをローカルでテストできる環境を整える

## はじめに
本記事ではPythonを例にAzure FunctionsのHTTP Triggerを作っていきます。
その中で、ローカル環境（Windows）でAzure Functionsの挙動を確認したいので、その方法をまとめます。

参考

https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-vs-code-python?pivots=python-mode-decorators

## VSCodeの拡張機能インストール
VScodeをインストールして、以下の拡張機能を入れる（Japenese、Python、Azure functions、Azurite）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/b9251bad-0146-3c87-ed5b-8e13808488f7.png)

### Core Tools
Ctrl+Shift+Pでコマンドパレットを開いて「Azure Functions: Core Tools のインストールまたは更新」を選択すると以下のようなメッセージが出る。なお、公式の動画内でも同じ動作となっていた（なんでやねん）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/5e141616-dd7c-057b-bc73-90b93522413e.png)

「these instructions」のリンクから「Windows 64-bit」を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/79a19cc5-7b20-8048-8b68-894649046959.png)

ダウンロードして実行すると以下のような画面が出るので進めていく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/05a0a0a0-18a4-5fab-0ff1-c6bcc7690b83.png)


インストール完了後コマンドプロンプトで以下のように出ればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/d9273d8f-37f6-422b-5996-d5a2a2265674.png)


## ローカルでAzure functionsを作る

「エクスプローラ」タブでプロジェクトを作りたいフォルダを作成し、選択しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/a0453583-3d1a-9bad-6866-8b250cad65e9.png)
今はTEST01フォルダを選択した。

VScodeの「azure」タブを選択し「signed in to Azure」でazureにサインインする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/1b5c2b4b-f83f-8feb-d295-7da46fe71a1a.png)
サインインできた。

「azure」タブの「workspace」の右側にazure functionsのマークがあるので、「Create Function」を選択する（わかりにくい）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/57613959-9680-4664-cc66-fd8b713c2fae.png)

以下の設定をコマンドパレットに入力していく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/e58072cf-9b02-0059-18c5-f4bd23a9303e.png)

プロジェクトが作成されたらlocal.settings.jsonを以下のように修正する。

```jsx:local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
  }
}
```
"AzureWebJobsStorage"を"UseDevelopmentStorage=true"にすることでローカルでBlobStorage等をエミュレーションする。この設定により、Azure Functionsをローカル環境でテストすることが可能になる。

Azurite:startを実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/dfc4e37b-7662-7fca-f770-192185377e3e.png)
ローカルのAzure Storageのエミュレーションが開始した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/efbb0c1b-ea5d-65aa-942c-282eb6ad5f5d.png)

「ターミナル」タブから「新しいターミナル」を選択する。
このままアプリを実行すると以下のようなエラーが出る。

```jsx
.venv\Scripts\activate : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\ncbpco101\VSProject\test01\.venv\Scripts\Ac
tivate.ps1 を読み込むことができません。詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照して
ください。
発生場所 行:1 文字:1
+ .venv\Scripts\activate ; func host start
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```

参考

https://rainbow-engine.com/ps-script-execution-disabled/

単純にPowershellのps1ファイルの実行ポリシーの制限によるものなので、powershellを管理者として開いて「set-executionpolicy remotesigned」を実行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/d4a6dc31-2ced-da76-bff6-31cc2a05fed0.png)
これでOK。

「F5」キーを押すとアプリを実行ができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/81e8cfb1-2d6e-b637-32c7-19f084c8b7cc.png)


```jsx:function_app.py
import azure.functions as func
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="http_trigger_test01")
def http_trigger_test01(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/38d685bc-32e9-9b54-2614-5ba0da730b2f.png)


## Azure Functionsに対して任意の入力を行う
関数がJSON形式で入力を待ち受けている状態なので、ローカルで関数に入力を与えてみる。

ターミナルにて関数を実行している状態で「azure」タブから関数を右クリックして「Execute Function Now」を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/3ca9e788-5bc3-922d-0cf7-e3ac79bb9f40.png)
エンター。

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/9e607915-3b9f-5c79-bb51-b3b4b138d8fa.png)


logging.infoした情報が「コンソール」タブから確認できる。
また、HttpResponseで返した内容はVSCodeの通知情報としてみることができる。

ローカルで作成したFunctionsをazureにデプロイする方法は以下を見ると丁寧。

https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-vs-code-python?pivots=python-mode-decorators#publish-the-project-to-azure

## 次回予告

Azure Functionsを使っていると、取得したデータ等を保管しておきたい要件が出ることもありますよね。
そこで、次回はAzure FunctionsとCosmos DBを連携させて、お手軽なアプリケーションを作ってみましょう。