状態には注意してください
状態によって、ステップがより密結合になり、再利用が困難になる可能性があります。
行わないでください。
シナリオは互いに独立している必要があるため、シナリオ間で状態を共有しないことが重要です。誤ってあるシナリオから別のシナリオに状態が漏洩すると、シナリオが脆くなり、個別に実行することが困難になります。
シナリオ間での状態の意図しない漏洩を防ぐために
Before
フックでデータベースをクリーンアップしてください。Before
フックでCookieを削除してください。シナリオ内では、ステップ間で状態を共有したい場合があります。
ステップ定義内で変数に状態を格納することができます。
Cucumber は各シナリオの前に各Glueコードクラスの新しいインスタンスを作成するため、ステップから状態が漏洩することはありません。
ScenarioScope
アノテーション を使用できます。このアノテーションにより、これらの Bean はシナリオ間で永続化されず、状態が漏洩しません。ScenarioScoped
を使用する必要があります。こちらも参照してください 依存性注入。
Cucumber は各シナリオの前に各Glueコードクラスの新しいインスタンスを作成するため、ステップから状態が漏洩することはありません。
ScenarioScope
アノテーション を使用できます。このアノテーションにより、これらの Bean はシナリオ間で永続化されず、状態が漏洩しません。ScenarioScoped
を使用する必要があります。こちらも参照してください 依存性注入。
Ruby では、Cucumber はシナリオをWorld
内で実行します。デフォルトでは、World
はObject
のインスタンスです。
すべてのステップ定義は現在のWorld
インスタンスのコンテキストで実行されます。各シナリオに対して新しいインスタンスが作成されます。つまり、ステップ定義ブロック内のself
はWorld
インスタンスになります。ステップ定義でインスタンス化された@instance_variable
はWorld
に割り当てられ、他のステップ定義からアクセスできます。
ヘルパーメソッドやログ出力など、World に動作を追加したい場合は、support/env.rb
で行うことができます。
module CustomWorld
def a_helper
...
end
end
World(CustomWorld)
これで、ステップ定義からa_helper
を呼び出すことができます。
すべてのシナリオはWorldの個別のインスタンスで実行されるため、シナリオ間で暗黙的な状態共有はありません。
World
にモジュールを含めることもできます。
module MyHelper
def some_other_helper
...
end
end
module CustomWorld
include MyHelper
def a_helper
...
end
end
World(CustomWorld)
Rspec や Webrat などの他のいくつかのフレームワークには、このようにWorld
に含めることができる特殊なメソッドを提供するモジュールがあります。
(独自のWorld
クラスを定義せず、デフォルトのObject
インスタンスを使用する場合)でも、グローバルなincludeでObject
を汚染することなく、World
インスタンスにモジュールを含めることができます。
module MyHelper
def some_other_helper
...
end
end
module MyOtherHelpers
def helper_b
...
end
end
World(MyHelper, MyOtherHelpers)
これにより、これらのモジュールを使用して各新しいWorld
オブジェクトが拡張されます。
Ruby on Railsを使用する場合は、既にWorld
が設定されているため、ActionDispatch::IntegrationTest
のサブクラスであるCucumber::Rails::World
のインスタンスを取得します。これにより、Rails の多くのヘルパーメソッドにアクセスできます。
Cucumber-js は、各シナリオに対して分離されたコンテキストとしてWorld
を使用します。詳細については、GitHub の cucumber-js ドキュメントを参照してください。
プログラミング言語が JVM 言語の場合、Glue コード(ステップ定義とフック)をクラスで記述します。
Cucumber は、各シナリオの前に、Glue コードクラスの新しいインスタンスを作成します。
Glue コードクラスに空のコンストラクタがある場合、他に何も必要ありません。ただし、ほとんどのプロジェクトでは、依存性注入 (DI) モジュールを使用してコードをより適切に整理し、ステップ定義間で状態を共有するとメリットがあります。
使用可能な依存性注入モジュールは次のとおりです。
プログラミング言語が JVM 言語の場合、Glue コード(ステップ定義とフック)をクラスで記述します。
Cucumber は、各シナリオの前に、Glue コードクラスの新しいインスタンスを作成します。
Glue コードクラスに空のコンストラクタがある場合、他に何も必要ありません。ただし、ほとんどのプロジェクトでは、依存性注入 (DI) モジュールを使用してコードをより適切に整理し、ステップ定義間で状態を共有するとメリットがあります。
使用可能な依存性注入モジュールは次のとおりです。
PicoContainer を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-picocontainer', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。詳細については、PicoContainer を使用した状態共有を参照してください。
PicoContainer を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-picocontainer', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。詳細については、PicoContainer を使用した状態共有を参照してください。
Spring を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-spring', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Spring を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-spring', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Guice を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-guice</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-guice', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。詳細については、Guice を使用した状態共有を参照してください。
Guice を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-guice</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-guice', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。詳細については、Guice を使用した状態共有を参照してください。
OpenEJB を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-openejb</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-openejb', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
OpenEJB を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-openejb</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-openejb', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Weld を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-weld</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-weld', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Weld を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-weld</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-weld', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Needle を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-needle</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-needle', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
Needle を使用するには、pom.xml
に次の依存関係を追加します。
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-needle</artifactId>
<version>7.20.1</version>
<scope>test</scope>
</dependency>
または、Gradle を使用している場合は、次を追加します。
compile group: 'io.cucumber', name: 'cucumber-needle', version: '7.20.1'
まだドキュメントはありませんが、コードはGitHubにあります。
DI フレームワークを使用する場合、ステップ定義、フック、トランスフォーマーなどはすべて、フレームワークのインスタンスインジェクターによって作成されます。
DI フレームワークを使用する場合、ステップ定義、フック、トランスフォーマーなどはすべて、フレームワークのインスタンスインジェクターによって作成されます。
Cucumber の例テストは通常小さく、依存関係はありません。しかし、現実の世界では、テストは多くの場合、インジェクターによって供給される必要があるアプリケーション固有のオブジェクトインスタンスへのアクセスを必要とします。これらのインスタンスをステップ定義で使用できるようにする必要があります。これにより、アクションを適用し、配信された結果をテストできます。
DI フレームワークを使用した Cucumber の使用が通常発生する理由は、テスト対象のアプリケーションでも同じフレームワークを使用しているためです。そのため、Cucumber で使用するカスタムインジェクターを構成する必要があります。このインジェクターは、テストとアプリケーションのインスタンスを結び付けます。
Google Guice を使用した典型的なステップ定義の例を次に示します。Cucumber 提供の Guice インジェクターを使用すると、必要な appService
メンバーをインスタンス化できず、失敗します。
package com.example.app;
import static org.junit.Assert.assertTrue;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.guice.ScenarioScoped;
import com.example.app.service.AppService;
import java.util.Objects;
import javax.inject.Inject;
@ScenarioScoped
public final class StepDefinition {
private final AppService appService;
@Inject
public StepDefinition( AppService appService ) {
this.appService = Objects.requireNonNull( appService, "appService must not be null" );
}
@When("the application services are started")
public void startServices() {
this.appService.startServices();
}
@Then("all application services should be running")
public void checkThatApplicationServicesAreRunning() {
assertTrue( this.appService.servicesAreRunning() );
}
}
AppServiceの実装には、通常Guiceモジュールによって提供される必要がある、追加の引数と設定が必要になる場合があります。Guiceモジュールはインジェクターの設定に使用され、次のようなものになります。
package com.example.app.service.impl;
import com.example.app.service.AppService;
import com.google.inject.AbstractModule;
public final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
bind( AppService.class ).to( AppServiceImpl.class );
// ... (further bindings)
}
}
実際のインジェクターは次のように作成されます: injector = Guice.createInjector( new ServiceModule() );
つまり、独自のインジェクターを作成し、Cucumberがそれを使用するように指示する必要があります。
Cucumber の例テストは通常小さく、依存関係はありません。しかし、現実の世界では、テストは多くの場合、インジェクターによって供給される必要があるアプリケーション固有のオブジェクトインスタンスへのアクセスを必要とします。これらのインスタンスをステップ定義で使用できるようにする必要があります。これにより、アクションを適用し、配信された結果をテストできます。
DI フレームワークを使用した Cucumber の使用が通常発生する理由は、テスト対象のアプリケーションでも同じフレームワークを使用しているためです。そのため、Cucumber で使用するカスタムインジェクターを構成する必要があります。このインジェクターは、テストとアプリケーションのインスタンスを結び付けます。
Google Guice を使用した典型的なステップ定義の例を次に示します。Cucumber 提供の Guice インジェクターを使用すると、必要な appService
メンバーをインスタンス化できず、失敗します。
package com.example.app;
import static org.junit.Assert.assertTrue;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.guice.ScenarioScoped;
import com.example.app.service.AppService;
import java.util.Objects;
import javax.inject.Inject;
@ScenarioScoped
public final class StepDefinition {
private final AppService appService;
@Inject
public StepDefinition( AppService appService ) {
this.appService = Objects.requireNonNull( appService, "appService must not be null" );
}
@When("the application services are started")
public void startServices() {
this.appService.startServices();
}
@Then("all application services should be running")
public void checkThatApplicationServicesAreRunning() {
assertTrue( this.appService.servicesAreRunning() );
}
}
AppServiceの実装には、通常Guiceモジュールによって提供される必要がある、追加の引数と設定が必要になる場合があります。Guiceモジュールはインジェクターの設定に使用され、次のようなものになります。
package com.example.app.service.impl;
import com.example.app.service.AppService;
import com.google.inject.AbstractModule;
public final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
bind( AppService.class ).to( AppServiceImpl.class );
// ... (further bindings)
}
}
実際のインジェクターは次のように作成されます: injector = Guice.createInjector( new ServiceModule() );
つまり、独自のインジェクターを作成し、Cucumberがそれを使用するように指示する必要があります。
Cucumberが特定のオブジェクトを必要とするたびに、オブジェクトファクトリを使用します。Cucumberにはデフォルトのオブジェクトファクトリがあり(Guiceの場合)、デフォルトのインジェクターを作成し、オブジェクトの作成をそのインジェクターに委任します。インジェクターをカスタマイズする場合は、独自のオブジェクトファクトリを提供し、代わりにそれをCucumberが使用するように指示する必要があります。
package com.example.app;
import io.cucumber.core.backend.ObjectFactory;
import io.cucumber.guice.CucumberModules;
import io.cucumber.guice.ScenarioScope;
import com.example.app.service.impl.ServiceModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
public final class CustomObjectFactory implements ObjectFactory {
private Injector injector;
public CustomObjectFactory() {
// Create an injector with our service module
this.injector =
Guice.createInjector( Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule());
}
@Override
public boolean addClass( Class< ? > clazz ) {
return true;
}
@Override
public void start() {
this.injector.getInstance( ScenarioScope.class ).enterScope();
}
@Override
public void stop() {
this.injector.getInstance( ScenarioScope.class ).exitScope();
}
@Override
public < T > T getInstance( Class< T > clazz ) {
return this.injector.getInstance( clazz );
}
}
これはGuiceのデフォルトのオブジェクトファクトリですが、インジェクターに独自のバインディングを追加しています。Cucumberはjava.util.ServiceLoader
を通じてオブジェクトファクトリを読み込みます。ServiceLoaderがカスタム実装を検出できるようにするには、META-INF/services/io.cucumber.core.backend.ObjectFactory
ファイルを提供する必要があります。
com.example.app.CustomObjectFactory
#
# ... additional custom object factories could be added here
#
これで、Cucumberがカスタムオブジェクトファクトリを使用するように指示する必要があります。これを実現する方法はいくつかあります。
Cucumberが特定のオブジェクトを必要とするたびに、オブジェクトファクトリを使用します。Cucumberにはデフォルトのオブジェクトファクトリがあり(Guiceの場合)、デフォルトのインジェクターを作成し、オブジェクトの作成をそのインジェクターに委任します。インジェクターをカスタマイズする場合は、独自のオブジェクトファクトリを提供し、代わりにそれをCucumberが使用するように指示する必要があります。
package com.example.app;
import io.cucumber.core.backend.ObjectFactory;
import io.cucumber.guice.CucumberModules;
import io.cucumber.guice.ScenarioScope;
import com.example.app.service.impl.ServiceModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
public final class CustomObjectFactory implements ObjectFactory {
private Injector injector;
public CustomObjectFactory() {
// Create an injector with our service module
this.injector =
Guice.createInjector( Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule());
}
@Override
public boolean addClass( Class< ? > clazz ) {
return true;
}
@Override
public void start() {
this.injector.getInstance( ScenarioScope.class ).enterScope();
}
@Override
public void stop() {
this.injector.getInstance( ScenarioScope.class ).exitScope();
}
@Override
public < T > T getInstance( Class< T > clazz ) {
return this.injector.getInstance( clazz );
}
}
これはGuiceのデフォルトのオブジェクトファクトリですが、インジェクターに独自のバインディングを追加しています。Cucumberはjava.util.ServiceLoader
を通じてオブジェクトファクトリを読み込みます。ServiceLoaderがカスタム実装を検出できるようにするには、META-INF/services/io.cucumber.core.backend.ObjectFactory
ファイルを提供する必要があります。
com.example.app.CustomObjectFactory
#
# ... additional custom object factories could be added here
#
これで、Cucumberがカスタムオブジェクトファクトリを使用するように指示する必要があります。これを実現する方法はいくつかあります。
Cucumberをコマンドラインから実行する場合、カスタムオブジェクトファクトリを引数として指定できます。
java io.cucumber.core.cli.Main --object-factory com.example.app.CustomObjectFactory
Cucumberをコマンドラインから実行する場合、カスタムオブジェクトファクトリを引数として指定できます。
java io.cucumber.core.cli.Main --object-factory com.example.app.CustomObjectFactory
Cucumberは、存在する場合、プロパティファイル(cucumber.properties
)を使用します。カスタムオブジェクトファクトリはこのファイルで指定でき、Cucumberの実行時に読み込まれます。cucumber.properties
ファイルには、次のエントリが必要です。
cucumber.object-factory=com.example.app.CustomObjectFactory
Cucumberは、存在する場合、プロパティファイル(cucumber.properties
)を使用します。カスタムオブジェクトファクトリはこのファイルで指定でき、Cucumberの実行時に読み込まれます。cucumber.properties
ファイルには、次のエントリが必要です。
cucumber.object-factory=com.example.app.CustomObjectFactory
JUnit 4とTestNG用のCucumberモジュールを使用すると、JUnit/TestNGテストを通じてCucumberを実行できます。カスタムオブジェクトファクトリは、@CucumberOptions
アノテーションを使用して設定できます。JUnit 5については、cucumber-junit-platform-engineのドキュメントを参照してください。
JUnit 4とTestNG用のCucumberモジュールを使用すると、JUnit/TestNGテストを通じてCucumberを実行できます。カスタムオブジェクトファクトリは、@CucumberOptions
アノテーションを使用して設定できます。JUnit 5については、cucumber-junit-platform-engineのドキュメントを参照してください。
Cucumberは多くの場合、イベントバスでイベントを発行します。例:-フィーチャファイルの解析中-テストシナリオの実行時
Cucumberは多くの場合、イベントバスでイベントを発行します。例:-フィーチャファイルの解析中-テストシナリオの実行時
各イベントには、一意の識別子としてUUIDがあります。UUIDジェネレーターは、cucumber.uuid-generator
プロパティを使用して設定できます。
| UUIDジェネレーター | 機能 | パフォーマンス[百万UUID/秒] | 代表的な使用例 | |——————————————————-|————————————————————————————————————————————————————————————————————|————————————|——————————————————————————————————————————————————————————————————————————————————————————–| | io.cucumber.core.eventbus.RandomUuidGenerator
|
io.cucumber.core.eventbus.IncrementingUuidGenerator
|実際のプロジェクトでのパフォーマンス向上は、フィーチャのサイズによって異なります。
ジェネレーターが指定されていない場合、RandomUuidGenerator
が使用されます。
各イベントには、一意の識別子としてUUIDがあります。UUIDジェネレーターは、cucumber.uuid-generator
プロパティを使用して設定できます。
| UUIDジェネレーター | 機能 | パフォーマンス[百万UUID/秒] | 代表的な使用例 | |——————————————————-|————————————————————————————————————————————————————————————————————|————————————|——————————————————————————————————————————————————————————————————————————————————————————–| | io.cucumber.core.eventbus.RandomUuidGenerator
|
io.cucumber.core.eventbus.IncrementingUuidGenerator
|実際のプロジェクトでのパフォーマンス向上は、フィーチャのサイズによって異なります。
ジェネレーターが指定されていない場合、RandomUuidGenerator
が使用されます。
RandomUuidGenerator
とIncrementingUuidGenerator
のどちらもプロジェクトのニーズに合わない場合は、カスタムUUIDジェネレーターを定義できます。これは、次の方法で行います。
java package mypackage.mysubpackage; import io.cucumber.core.eventbus.UuidGenerator; public class MyUuidGenerator implements UuidGenerator { @Override public UUID generateId() { return ... } }
META-INF/services/io.cucumber.code.eventbus.UuidGenerator
(例:Mavenのresources
ディレクトリ)を使用して、ジェネレーターのクラス名を含むSPIとしてUUIDジェネレーターを定義します:java mypackage.mysubpackage.MyUuidGenerator
このUUIDジェネレーターは、デフォルトのRandomUuidGenerator
をオーバーライドします。
META-INF/services/...
ファイルに複数のUUIDジェネレーターが含まれている場合、またはクラスパスに複数のMETA-INF/services/...
がある場合、cucumber.uuid-generator
プロパティを設定して、目的のジェネレーターを選択する必要があります。
RandomUuidGenerator
とIncrementingUuidGenerator
のどちらもプロジェクトのニーズに合わない場合は、カスタムUUIDジェネレーターを定義できます。これは、次の方法で行います。
java package mypackage.mysubpackage; import io.cucumber.core.eventbus.UuidGenerator; public class MyUuidGenerator implements UuidGenerator { @Override public UUID generateId() { return ... } }
META-INF/services/io.cucumber.code.eventbus.UuidGenerator
(例:Mavenのresources
ディレクトリ)を使用して、ジェネレーターのクラス名を含むSPIとしてUUIDジェネレーターを定義します:java mypackage.mysubpackage.MyUuidGenerator
このUUIDジェネレーターは、デフォルトのRandomUuidGenerator
をオーバーライドします。
META-INF/services/...
ファイルに複数のUUIDジェネレーターが含まれている場合、またはクラスパスに複数のMETA-INF/services/...
がある場合、cucumber.uuid-generator
プロパティを設定して、目的のジェネレーターを選択する必要があります。
シナリオ間での状態のリークを防ぐために、データベースから状態を削除する方法はいくつかあります。
シナリオ間でデータベースをクリーンアップする推奨されるアプローチは、シナリオの開始前にすべてのデータを削除するBefore
フックを使用することです。これは、After
フックを使用するよりも通常は優れており、シナリオが失敗した場合にデータベースの事後検査を実行できます。
別の方法として、データベーストランザクションを使用できます。
データベースがサポートしている場合、各シナリオの周囲にトランザクションをラップできます。
これにより、シナリオが高速化される可能性がありますが、コストがかかります。事後検査を実行できなくなり、ブラウザの自動化を使用できなくなります。
このアプローチを使用するには、Before
フックでトランザクションを開始し、後でAfter
フックでロールバックするようにCucumberに指示する必要があります。
これは非常に一般的なことなので、いくつかのCucumber拡張機能は、@txn
というタグを使用した、すぐに使用できる条件付きフックを提供しています。
有効にするには、トランザクションが必要なすべてのフィーチャまたはシナリオに@txn
タグを付ける必要があります。
@txn
Feature: Let's write a lot of stuff to the DB
Scenario: I clean up after myself
Given I write to the DB
Scenario: And so do I!
Given I write to the DB
最小限の設定については、Cucumber-JVMのspring-java-junit5の例を参照してください。
最小限の設定については、Cucumber-JVMのspring-java-junit5の例を参照してください。
HTTP経由でアプリケーションと通信するブラウザの自動化ツールを使用している場合、ステップ定義とHTTPリクエストを提供するWebアプリケーションがそれぞれ独自のデータベース接続を持っている場合、トランザクションアプローチは機能しません。トランザクションがオンの場合、トランザクションはデータベースに決してコミットされません(ただし、各シナリオの最後にロールバックされます)。したがって、Webサーバーの接続はCucumberからのデータを確認せず、したがってブラウザも確認しません。同様に、Cucumberの接続はWebサーバーからのデータを確認しません。
この場合、データベーストランザクションをオフにし、各シナリオの前にテストデータが明示的に削除されるようにする必要があります。
Ruby on Railsを使用している場合、フィーチャまたは特定のシナリオのトランザクションをオフにすることができます。次のように@no-txn
タグを使用します。
@no-txn
Feature: Lots of Scenarios with transactions off.
この場合は、各シナリオの前にデータが明示的に削除される総当たりアプローチを使用する必要があります。または、これです。
Feature: ...
@no-txn
Scenario: One Scenario with transactions off.
Railsでは、features/support/env.rb
でグローバルにトランザクションをオフにすることもできます。
Cucumber::Rails::World.use_transactional_fixtures = false
Ruby on Railsを使用している場合、これに対処するための優れたツールはBen MabeyのDatabase Cleaner gemです。これはgem install database_cleaner
でインストールできます。
これは@no-txn
タグと非常に効果的に使用できます。たとえば、次のようなものをfeatures/support/db_cleaner.rb
などに追加します。
require 'database_cleaner'
DatabaseCleaner.clean_with :truncation # clean once to ensure clean slate
DatabaseCleaner.strategy = :truncation
Before('@no-txn') do
DatabaseCleaner.start
end
After('@no-txn') do
DatabaseCleaner.clean
end
Railsを使用していない場合は、次のコードを使用してRubyでDatabaseCleaner
を使用して、@no-txn
の動作全体を再現できます。
# With this you should be able to tag the stories that need to use truncation.
# Otherwise, the transaction strategy will be used all the other times.
require 'database_cleaner'
DatabaseCleaner.clean_with :truncation # clean once to ensure clean slate
DatabaseCleaner.strategy = :transaction # use transactions by default
Before('@no-txn') do
DatabaseCleaner.strategy = :truncation
end
Before do
DatabaseCleaner.start
end
After do
DatabaseCleaner.clean
end
After('@no-txn') do
DatabaseCleaner.strategy = :transaction
end
このドキュメントの改善にご協力いただけます。このページを編集。