単体テストが必要なのは誰ですか? あなたのためではありません-あなたのコードは完璧です。 それでも、この記事を読むだけで、Swiftでの単体テストの記述について詳しく説明できます。 突然、これは後で便利になります。
ユニットテストは、完璧なコードを書くための素晴らしい方法です。 テストは、プロジェクト作成の初期段階でエラーの大部分を見つけるのに役立ちます。 経験が示すように、コードのテストが困難な場合、そのサポートまたはデバッグが困難になります。
単体テストは、孤立した「マイクロコンポーネント」で動作します。 多くの場合、クラスを「ウェット」にする必要があります。つまり、テストできるように、特定のマイクロコンポーネントを分離するための偽の機能実装を提供します。
Objective-Cには、これを実装するのに役立ついくつかのサードパーティフレームワークがあります。 しかし、
Swiftではまだ利用できません。
このガイドでは、お友達の誕生日を思い出すのに役立つ簡単なアプリケーションをテストでカバーするために、独自のモックオブジェクト、偽物、およびスタブを作成する方法を学習します。
さあ始めましょうスタータープロジェクトをダウンロードするこれは連絡先ストレージアプリケーションです。 基本アプリケーションの機能には取り組みません。 むしろ、アプリケーションが正常に動作していることを確認するためのテストをいくつか作成します。
アプリケーションをコンパイルして実行し、動作をテストします。
プラスボタンをクリックして、
John Appleseedを共有連絡先リストに追加します。

連絡先を保存するために、アプリケーションは
Core Dataを使用します。

パニックにならないでください! このチュートリアルでは
コアデータの経験は必要ありません。 このため、特別なスキルは必要ありません。
単体テストの長所と短所テストの作成に関しては、良いニュースと悪いニュースの両方に出くわします。 残念なことに、ユニットテストには次のような欠点があります。
- 大量のコード:テストカバレッジが大きいプロジェクトでは、機能的なコードよりも多くのテストがある場合があります。
- より多くのサポート:より多くのコード、より多くのサポートが必要です。
- 適切なソリューションはありません。ユニットテストは保証されておらず、コードにエラーがないことを保証することはできません。
- もっと時間がかかります:テストの作成には時間がかかります-habrahabr.ruで新しい情報を学ぶのに費やすことができる時間です!
完全な解決策はありませんが、明るい面があります。テストを書くことには、次の利点があります。
- 自信:コードが機能することを確認できます。
- クイックレビュー:ユニットテストを使用すると、ナビゲーションの多くのレイヤーの下に隠れているコードを手動でテストできます-手動でチェックする必要があるコンポーネントが多すぎます。
- モジュール性:ユニットテストは、よりモジュール化されたコードの記述に集中するのに役立ちます。
- オリエンテーション:マイクロコンポーネントのテストを作成すると、細かい部分に集中できます。
- 回帰:前に修正したエラーが修正されたままであり、その後の修正が破損しないことを確認してください。
- リファクタリング: Xcodeがコードを独自に書き換えるのに十分スマートになるまで、リファクタリングを検証するためのユニットテストが必要になります。
- ドキュメント:ユニットテストでは、コードが何をすべきかを説明します。 コードを記述する別の方法です。
基本的なアプリケーション構造アプリケーションの大量のコードは、
コアデータが有効になっている
マスター/詳細アプリケーションテンプレートに基づいています。 ただし、コードテンプレートにはいくつかの重要な改善点があります。
Xcodeでプロジェクトを開き、プロジェクトナビゲーターを確認します。

以下の詳細を考慮してください。
- Person.swiftファイルとPersonInfo.swiftファイルがあります。 PersonクラスはNSManagedObjectの子孫であり 、各人に関する基本的な情報が含まれています。 PersonInfo構造には同じ情報が含まれていますが、アドレス帳から更新できます。
- PeopleListフォルダーには、View Controller、データプロバイダー、およびデータプロバイダープロトコルの3つのファイルがあります。
PeopleView内のファイルのコレクションは、大きなView Controllerを回避します。 大きなView Controllerを回避するために、単純なプロトコルを介してView Controllerに接続する他のクラスに一部の責任をシフトできます。
古い興味深い
記事ではありますが、この興味深い
記事を読むことで、大規模なView Controllerとその回避方法について学ぶことができます。
この場合、プロトコルは
PeopleListDataProviderProtocol.swiftで定義されています。 それを開いて見てください。 このプロトコルに準拠するクラスには、プロパティ
managedObjectContextおよび
tableViewが必要であり、
addPerson(_ :)および
fetch()メソッドを定義する必要があります。 さらに、
UITableViewDataSourceプロトコルに準拠する必要があります。
ビューコントローラー
PeopleListViewControllerには、
PeopleListDataProviderProtocolプロトコルに準拠する
dataProviderプロパティがあります。 このプロパティは、AppDelegate.swiftファイルのPeopleListDataProviderインスタンスに設定されます。
ABPeoplePickerNavigationControllerを使用して、連絡先リストに新しい人を追加します。 このクラスを使用すると、開発者は許可なしにユーザーの連絡先にアクセスできます。
PeopleListDataProviderは 、Table Viewに
データを取り込み、
Core Dataにアクセスする役割を果たします。
注:プロジェクト内のいくつかのクラスとメソッドはパブリックとして宣言されています。 テストターゲットがクラスとメソッドにアクセスできるようにします。 テストの対象は、アプリケーションモジュールの外部です。 アクセス修飾子を追加しない場合、クラスとメソッドは
internalとして定義されます。 これは、同じモジュールでのみ利用できることを意味します。 モジュールの外部から(たとえば、テストのターゲットから)それらにアクセスするには、
パブリックアクセス
修飾子を追加する必要があります。
それでは、テストを作成しましょう!
モックオブジェクトの作成モックオブジェクトを使用すると、メソッド呼び出しが行われたか、プロパティが設定されているかを確認できます。 たとえば、
PeopleListViewControllerのviewDidLoad()では、テーブルビューが
dataProviderの tableViewプロパティに設定され
ます 。
実際に何が起こっているのかを確認するテストを作成します。
テスト用のアプリケーションの準備まず、テストを作成するためのプロジェクトを準備する必要があります。
プロジェクトナビゲータでプロジェクトを選択し、誕生日テストターゲットで
ビルド設定を選択します。 以下に示すように、
Definesモジュールを見つけて、設定を
Yesに変更します。

次に、
BirthdaysTestsフォルダーを選択し、
File \ New \ File ...を参照し
ます。 iOS \ Source \ Test Case Classを選択して、Nextをクリックし、
PeopleListViewControllerTestsという名前を付け、
Swiftファイルを作成したことを確認し、もう一度
Nextをクリックしてから
Createをクリックし
ます 。
Xcodeで結合ヘッダーを作成するように求められたら、[
いいえ]を選択します
。 これは、ターゲットにファイルがなく、新しい
Swiftファイルを追加したときに発生する
Xcodeのエラーです。
新しく作成した
PeopleListViewControllerTests.swiftを開きます。 以下に示すように、
import Birthdaysステートメントを他のimportステートメントの直後に追加して、オンにしたばかりのモジュールをインポートします。
import UIKit import XCTest import Birthdays
次の2つの定型的な方法を削除します。
func testExample() {
PeopleListViewControllerのインスタンスが必要になったため、テストで使用できます。
PeopleListViewControllerTestsの上部に次の行を追加します
var viewController: PeopleListViewController!
次に、setUp()メソッドを次のコードに置き換えます。
override func setUp() { super.setUp() viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("PeopleListViewController") as! PeopleListViewController }
ストーリーボードを使用して
PeopleListViewControllerをインスタンス化し、それを
viewControllerに割り当てます。
Product \ Testを選択します。
Xcodeはプロジェクトをコンパイルし、既存のテストを実行します。 テストはまだありませんが、これにより、すべてが正しく構成されていることを確認できます。 数秒後、
Xcodeはすべてのテストが成功したことを報告するはずです。
これで、最初のモックオブジェクトを作成する準備ができました。
最初のMockオブジェクトを書くCore Dataで作業するため、
Birthishsの
インポート行の直後に
PeopleListViewControllerTests.swiftまで次のインポートを追加します。
import CoreData
次に、次のコードを
PeopleListViewControllerTestsクラス
定義に追加します。
class MockDataProvider: NSObject, PeopleListDataProviderProtocol { var managedObjectContext: NSManagedObjectContext? weak var tableView: UITableView! func addPerson(personInfo: PersonInfo) { } func fetch() { } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return UITableViewCell() } }
これはかなり複雑なモックオブジェクトのようです。 ただし、このモッククラスのインスタンスを
PeopleListViewController dataProviderプロパティに割り当てるため、これは単に最低限必要な最小限のものです。 モッククラスは、
PeopleListDataProviderProtocolおよび
UITableViewDataSourceプロトコルにも準拠する必要があります。
Product \ Testを選択します。 プロジェクトが再度コンパイルされ、テストがUrに合格します。 しかし、モックオブジェクトを使用した最初のユニットテスト用にすべてを設定できました。
単体テストは、3つの部分に分け、名前を付け、
指定された 、
いつ 、およびの
順にする必要があります。 '
Given 'は環境を設定します。 '
when 'は、テストする必要のあるコードを実行します。 「then」は期待される結果を確認します。
テストでは、
viewDidLoad()メソッドの実行後に
データプロバイダーの
tableViewプロパティが設定され
ていることを確認します。
PeopleListViewControllerTestsに次のテストを追加します
。 func testDataProviderHasTableViewPropertySetAfterLoading() {
上記のテストの仕組みは次のとおりです。
- MockDataProviderのインスタンスを作成し、dataProviderのView Controllerプロパティに設定します。
- テストを開始する前に、tableViewプロパティがnilであることを確認します。
- viewDidLoad()を実行するビューにアクセスできます。
- テストクラスtableViewのプロパティがnilではなく、プロパティがView ControllerのtableViewに設定されていることを確認します。
次に、
Product \ Testを再度選択します。 テストが完了したらすぐに、ナビゲーターを開きます(
Cmd + 5-便利なショートカットキー)。 次のように表示されます。

モックオブジェクトを使用した最初のテストは成功しました!
addPerson(_ :)メソッドのテスト次のテストでは、リストから連絡先を選択すると
addPerson(_ :)メソッドが呼び出されることを確認します
次のプロパティを
MockDataProviderクラスに追加します。
var addPersonGotCalled = false
次に、
addPerson(_ :)メソッドを次のものに置き換えます。
func addPerson(personInfo: PersonInfo) { addPersonGotCalled = true }
ここで、
addPerson(_ :)を呼び出すときに、
trueを
MockDataProviderに設定してインスタンスに登録します。
この動作をテストするメソッドを追加する前に、
AddressBookUIフレームワークをインポートする必要があります。
PeopleListViewControllerTests.swiftに次のインポートを追加します。
import AddressBookUI
次のテストメソッドを残りのテストスクリプトに追加します。
func testCallsAddPersonOfThePeopleDataSourceAfterAddingAPersion() {
ここで何が起こっているのでしょうか?
- 最初に、View Controllerデータプロバイダーを偽のデータプロバイダーのインスタンスにインストールします。
- 次に、 ABPersonCreate()を使用して連絡先を作成します。
- ここでは、デリゲートメソッドpeoplePickerNavigationController(_:didSelectPerson :)を手動で呼び出します。 デリゲートメソッドを手動で手動で呼び出すことは、悪いコードの兆候ですが、テストの目的には適しています。
- 最後に、 addPerson(_ :)が呼び出されたことを確認し、 addPersonGotCalledがtrueであることを確認します。
Product \ Testを選択して、
テストを実行します。 これは非常に簡単な作業であることがわかりました!
しかし、待ってください! 時間をかけてください! テストが実際にあなたがテストしたと思うものをテストすることをどうやって知っていますか
テストを確認するテストが実際に何かをチェックしていることを確認する簡単な方法は、テストがチェックしているオブジェクトを削除することです。
PeopleListViewController.swiftを開き 、次の行
peoplePickerNavigationController(_:didSelectPerson :)をコメントアウトします 。
dataProvider?.addPerson(person)
テストを再度実行します。 今書いた最後のテストは失敗するはずです。 傑作-あなたのテストは実際に何かをテストしていることを知っています。 テストを確認してください。 少なくとも、最も複雑なテストをチェックして、それらが機能することを確認する必要があります。

行のコメントを解除して、コードを動作状態に戻します。 テストを再度実行して、すべてが機能していることを確認します。
Apple FrameworkクラスのモックNSUserDefaults.standardUserDefaults()や
NSNotificationCenter.defaultCenter()などの
シングル トーンを使用できますが、デフォルト値をどのようにテストしますか?
Appleは、これらのクラスのステータスを確認することを許可していません。
期待される結果のオブザーバーとしてテストクラスを追加できます。 ただし、これらのクラスの実装に依存するため、テストの速度が低下し、信頼性が低下する可能性があります。 または、コードの別の部分から値を設定でき、孤立した動作をテストしませんでした。
これらの制限を回避するには、これらのシングルトーンの代わりにモックオブジェクトを使用できます。
注: Appleクラスを模擬オブジェクトに置き換える場合、実装の詳細はいつでも変更される可能性があるため、そのクラスの動作ではなく、そのクラスとの相互作用を確認することが非常に重要です。
アプリケーションをコンパイルして実行します。
John Appleseedと
David Taylorを人のリストに追加し、
「姓」と
「 名」の間でソートを切り替えます。 リスト内の連絡先の順序は並べ替えに依存することがわかります。
ソートを担当するコードは、
PeopleListViewController.swiftのchangeSort()メソッドにあります。
@IBAction func changeSorting(sender: UISegmentedControl) { userDefaults.setInteger(sender.selectedSegmentIndex, forKey: "sort") dataProvider?.fetch() }
NSUserDefaultsのキーでソートするために選択されたセグメントインデックスを追加し、
fetch()メソッドを呼び出します。
fetch()メソッドは、
NSUserDefaultsでこの新しいソート順を読み取り、
PeopleListDataProviderで示されている連絡先リストを更新する必要があります。
let sortKey = NSUserDefaults.standardUserDefaults().integerForKey("sort") == 0 ? "lastName" : "firstName" let sortDescriptor = NSSortDescriptor(key: sortKey, ascending: true) let sortDescriptors = [sortDescriptor] fetchedResultsController.fetchRequest.sortDescriptors = sortDescriptors var error: NSError? = nil if !fetchedResultsController.performFetch(&error) { println("error: \(error)") } tableView.reloadData() }
PeopleListDataProviderは
NSFetchedResultsControllerを使用して
Core Dataからデータを取得します。 リストの並べ替えを置き換えるには、
fetch()は並べ替え記述子を使用して配列を作成し、選択した結果コントローラーの選択クエリに設定します。 その後、フェッチしてリストを更新し、テーブルで
reloadData()メソッドを呼び出します。
NSUserDefaultsでユーザーの優先ソート順が正しく設定されていることを確認するテストを追加し
ます 。
PeopleListViewControllerTests.swiftを開き 、
Mockdataproviderクラス
定義の下に次のクラス定義を追加します。
class MockUserDefaults: NSUserDefaults { var sortWasChanged = false override func setInteger(value: Int, forKey defaultName: String) { if defaultName == "sort" { sortWasChanged = true } } }
MockUserDefaultsは
NSUserDefaultsのサブクラスです。 デフォルト値が
falseの booleanプロパティ
sortWasChangedがあります。 また、
setInteger(_:forKey :)メソッドをオーバーライドし、
sortWasChanged値を
trueに変更し
ます 。
PeopleListViewControllerTestsクラスの最後のテストの下に次のテストを追加します。
func testSortingCanBeChanged() {
このチェックのレポートは次のとおりです。
- 最初にMockUserDefaultsのインスタンスをView ControllerのuserDefaultsに割り当てます。 この手法は、依存性注入として知られています。
- 次に、 UISegmentedControlのインスタンスを作成し、View Controllerを.ValueChangedのターゲットとして追加します。
- 最後に、 setInteger(_:forKey :)ユーザーのモックがデフォルトで呼び出されたことを確認します。 値が実際にNSUserDefaultsに保存されたかどうかを確認していることに注意してください。
テストスイートを実行します。すべてが正常に完了するはずです。
本当に複雑なAPIまたはフレームワークを持っているが、小さなコンポーネントを本当にテストしたい場合は、フレームワークを深く掘り下げないでください。
それは、あなたがそれを「偽造」し、作成しないときです! :]
偽物オブジェクトの作成偽物オブジェクトは、偽物のクラスの完全な実装のように動作します。 それらは、扱いにくいクラスまたは構造の代わりとして使用します。
アプリケーションの場合、レコードを追加して
Core Dataで選択する必要はありません。 そのため、代わりに
Core Dataを偽造します。 少し恐ろしいですね。
BirthdaysTestsフォルダーを選択し、
File \ New \ File ...に移動します。 iOS \ Source \ Test Case Classテンプレートを選択し、
Nextをクリックします。 クラスに
PeopleListDataProviderTestsという名前を付け、「
次へ」をクリックしてから
「 作成 」をクリックし
ます 。
作成したテストクラスの不要なテストを再度削除します。
func testExample() {
次の2つのインポートを新しいクラスに追加します。
import Birthdays import CoreData
次に、次のプロパティを追加します。
var storeCoordinator: NSPersistentStoreCoordinator! var managedObjectContext: NSManagedObjectContext! var managedObjectModel: NSManagedObjectModel! var store: NSPersistentStore! var dataProvider: PeopleListDataProvider!
プロパティには、
コアデータスタックで使用される主要コンポーネントが含まれています。
Core Dataの使用を開始するには、
Core Dataチュートリアルをご覧ください。次のコードを
setUp()メソッドに追加します。
上記のコードで起こることは次のとおりです。
- setUp()は、メモリ内のストレージを使用して管理対象オブジェクトのコンテキストを作成します。 通常、 コアデータはデバイスのファイルシステム内のファイルです。 これらのテストでは、デバイスのメモリに「永続的な」ストレージを作成します。
- 次に、PeopleListDataProviderのインスタンスと、管理対象オブジェクトコンテキストを作成し、管理対象オブジェクトコンテキストを管理対象オブジェクトコンテキストとして設定されたメモリに保存します。 これは、新しいデータプロバイダーが実際のように動作することを意味しますが、Core Dataでオブジェクトを追加または削除しません。
次の2つのプロパティを
PeopleListDataProviderTestsに追加します。
var tableView: UITableView! var testRecord: PersonInfo!
次に、
setUp()メソッドの最後に次のコードを追加します。
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("PeopleListViewController") as! PeopleListViewController viewController.dataProvider = dataProvider tableView = viewController.tableView testRecord = PersonInfo(firstName: "TestFirstName", lastName: "TestLastName", birthday: NSDate())
これにより、ストーリーボードでView Controllerをインスタンス化してTable Viewをセットアップし、テストで使用するPersonInfoのインスタンスを作成します。
テストが完了したら、管理対象エンティティのコンテキストを「リセット」する必要があります。
tearDown()メソッド
を次のコードに置き換えます。
override func tearDown() { managedObjectContext = nil var error: NSError? = nil XCTAssert(storeCoordinator.removePersistentStore(store, error: &error), "couldn't remove persistent store: \(error)") super.tearDown() }
このコードは、managedObjectContextをnilに設定してメモリを解放し、ストアコーディネーターから永続ストアを削除します。 新しいテストリポジトリを使用して各テストを実行できます。
今-テストを書くことができます! 次のテストをテストクラスに追加します。
func testThatStoreIsSetUp() { XCTAssertNotNil(store, "no persistent store") }
このテストでは、ストレージが空ではないことを確認します。 新しいテストを実行します-すべてが成功するはずです。
次のテストでは、データソースが予想される行数を提供するかどうかを確認します。
次のテストをテストクラスに追加します。
func testOnePersonInThePersistantStoreResultsInOneRow() { dataProvider.addPerson(testRecord) XCTAssertEqual(tableView.dataSource!.tableView(tableView, numberOfRowsInSection: 0), 1, "After adding one person number of rows is not 1") }
最初に連絡先をテストリポジトリに追加してから、行数が1であることを確認します。
テストを実行します-すべて成功するはずです。
偽の「永続的な」ストレージを作成することにより、迅速なテストを提供し、ディスクをクリーンな状態に保つことができるため、起動時にアプリケーションが期待どおりに動作することを確認できます。
テストを書いた2つ以上のテスト連絡先を追加した後、セクションと行の数を確認することもできます。 それはすべて、プロジェクトで達成しようとしている自信のレベルに依存します。
プロジェクトで一度に複数のチームと作業したことがある場合、プロジェクトのすべての部分が同時に準備ができているわけではないことを知っていますが、すでにコードをテストする必要があります。 しかし、Webサービスなど、存在しないものについてコードの一部をどのようにテストできますか?
スタブがあなたの助けになります!
スタブを書くスタブはオブジェクトメソッド呼び出しへの応答を偽装します。 スタブを使用して、まだ開発中のWebサービス呼び出しコードをテストします。
プロジェクトのWebチームは、アプリケーションと同じ機能を備えたWebサービスの作成を任されました。 ユーザーはサービスにアカウントを作成し、アプリケーションとサービス間でデータを同期できます。 しかし、Webチームは作業の一部を開始することさえしなかったため、ほぼ完了です。 スタブを作成してWebサーバーコンポーネントを置き換える必要があるようです。
このセクションでは、2つのメソッドのテストの作成に焦点を当てます。1つはサイトに追加された連絡先を選択する方法、もう1つはアプリケーションからWebサービスに連絡先を追加する方法です。 実際のシナリオでは、ユーザー名とアカウント、およびエラー処理が必要になりますが、別のときに行います。
APICommunicatorProtocol.swiftを開き
ます 。 このプロトコルは、Webサービスから連絡先を受信し、連絡先を追加するための2つのメソッドを宣言します。
Personのインスタンスを移動できますが、管理対象エンティティには別のコンテキストが必要です。 この場合、構造の使用がはるかに簡単になりました。
次に、スタブを作成して、View Controllerと
APICommunicatorインスタンスの相互作用をサポートします。
PeopleListViewControllerTests.swiftを開き、
PeopleListViewControllerTestsクラス内に次のクラス定義を追加します。
注意すべきこと:
- APICommunicatorが構造体であっても、モックの実装はクラスです。 この場合、テストではデータを変更する必要があるため、クラスを使用する方が便利です。 これは、構造よりもクラスで行う方が少し簡単です。
- getPeople()メソッドは、allPersonInfoに保存されているものを返します。 ネットワークからデータをダウンロードする代わりに、単純な配列に連絡先情報を保存するだけです。
- postPerson(_ :)メソッドは、postPersonGotCalledにtrueを設定します。
スタブAPIをテストして、
addPerson()メソッドを呼び出したときに、APIから返されるすべての連絡先がリポジトリに追加されることを確認します
PeopleListViewControllerTestsに次のテストメソッドを追加します。
func testFetchingPeopleFromAPICallsAddPeople() {
上記のコードで起こることは次のとおりです。
- 最初に、テストで使用するmockDataProviderおよびmockCommunicatorシミュレートオブジェクトを構成します。
- 次に、偽の連絡先を作成し、 fetchPeopleFromAPI()メソッドを呼び出して偽のネットワーク呼び出しを行います。
- 最後に、 addPerson(_ :)メソッドをテストします。
テストをコンパイルして実行します。
それでは、次は何ですか?プロジェクトの最終バージョンをダウンロードします 。このバージョンには、この記事では説明しなかった追加のテストも含まれています。
アプリケーションのマイクロコンポーネントをテストするための模擬オブジェクト、偽物、およびスタブの作成方法を学び、
Swiftで XCTestがどのように
機能するかを理解しました。
この記事では、テストの最初の理解のみを示します。 アプリケーションのテストを作成するためのアイデアがすでにあると確信しています。
単体テストの詳細については、
テスト駆動開発(TDD)および
動作駆動開発(BDD)をご覧ください。 これらは、コードを書く前にテストを書くアプリケーション開発方法論です(そして、率直に言って、まったく新しい考え方を表します)。
単体テストは、完全なテストスイートの一部にすぎません。 包括的なテストは次の論理的なステップです。 包括的なテストを開始する簡単な方法は、
UIAutomationを使用することです。 アプリケーションのテストを真剣に考えている場合は、
UIAutomationを使用する必要があります。
psこの記事は2015年9月9日より前に作成されたため、サンプルの作成にはSwiftバージョン1.2が使用されました。 Swift言語の新しいバージョンのリリースに関連して、例にいくつかの変更を加えました。 プロジェクトのソースコードは、
こちらと
こちらにあり
ます 。