Java自動化テストフレームワーク-09-TestNGの依存注入編(詳細チュートリアル)

16142 ワード

1.-依存注入
TestNGは、2つの異なるタイプの依存注入をサポートします.ネイティブ(TestNG自体によって実行されます)と外部(Guiceなどの依存注入フレームワークによって実行されます).
1.1-ネイティブ依存注入
TestNGでは、メソッドに他のパラメータを宣言できます.このような場合、TestNGはこれらのパラメータを自動的に正しい値で埋めます.依存注入は、次の場所で使用できます.
任意の@Beforeメソッドまたは@Testメソッドは、ITestContextタイプのパラメータを宣言できます.どの@AfterMethodメソッドでも、実行したばかりのテストメソッドの結果を反映するITestResultタイプのパラメータを宣言できます.任意の@Beforeメソッドおよび@Afterメソッド(@BeforeSuiteおよび@AfterSuiteを除く)は、現在のタグを含むXmlTestタイプのパラメータを宣言できます.任意の@BeforeMethod(@AfterMethod)はjavaを宣言できます.lang.reflect.Methodタイプのパラメータ.このパラメータは、@BeforeMethodが完了した後(または@AfterMethodのために実行されたメソッドの後)に呼び出されるテストメソッドを受信します.任意の@BeforeMethodは、Object[]タイプのパラメータを宣言できます.このパラメータは、JavaのようなTestNGによって注入することができる、間もなく到来する試験方法のパラメータリストを受信する.lang.reflect.Methodまたは@DataProviderから.任意の@DataProviderは、ITestContextまたはjavaを宣言できます.lang.reflect.Methodタイプのパラメータ.次のパラメータは、呼び出すテストメソッドを受信します.@NoInjectionコメントを使用して、注入を閉じることができます.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public class NoInjectionTest {
 
  @DataProvider(name = "provider")
  public Object[][] provide() throws Exception {
      return new Object[][] { { CC.class.getMethod("f") } };
  }
 
  @Test(dataProvider = "provider")
  public void withoutInjection(@NoInjection Method m) {
      Assert.assertEquals(m.getName(), "f");
  }
 
  @Test(dataProvider = "provider")
  public void withInjection(Method m) {
      Assert.assertEquals(m.getName(), "withInjection");
  }
}

次の表では、さまざまなTestNGコメントにローカルに注入できるパラメータのタイプをまとめます.
Annotation
 ITestContext 
 XmlTest 
 Method 
 Object[] 
 ITestResult 
BeforeSuite
Yes
No
No
No
No
BeforeTest
Yes
Yes
No
No
No
BeforeGroups
Yes
Yes
No
No
No
BeforeClass
Yes
Yes
No
No
No
BeforeMethod
Yes
Yes
Yes
Yes
Yes
Test
Yes
No
No
No
No
DataProvider
Yes
No
Yes
No
No
AfterMethod
Yes
Yes
Yes
Yes
Yes
AfterClass
Yes
Yes
No
No
No
AfterGroups
Yes
Yes
No
No
No
AfterTest
Yes
Yes
No
No
No
AfterSuite
Yes
No
No
No
No
1.2-Guice依存注入
Guiceを使用する場合、TestNGは簡単な方法を提供し、Guiceモジュールを通じてテスト対象を注入することができます.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
@Guice(modules = GuiceExampleModule.class)
public class GuiceTest extends SimpleBaseTest {
 
  @Inject
  ISingleton m_singleton;
 
  @Test
  public void singletonShouldWork() {
    m_singleton.doSomething();
  }
 
}

この例では、GuiceExampleModuleがインタフェースISingletonを特定のクラスにバインドすると予想されます.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public class GuiceExampleModule implements Module {
 
  @Override
  public void configure(Binder binder) {
    binder.bind(ISingleton.class).to(ExampleSingleton.class).in(Singleton.class);
  }
 
}

どのモジュールを使用してクラスをインスタンス化するかを指定する柔軟性が必要な場合は、モジュールファクトリを指定できます.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
@Guice(moduleFactory = ModuleFactory.class)
public class GuiceModuleFactoryTest {
 
  @Inject
  ISingleton m_singleton;
 
  @Test
  public void singletonShouldWork() {
    m_singleton.doSomething();
  }
}

モジュールファクトリでは、インタフェースを実装する必要があります.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public interface IModuleFactory {
 /**
   * @param context The current test context
   * @param testClass The test class
   *
   * @return The Guice module that should be used to get an instance of this
   * test class.
   */
  Module createModule(ITestContext context, Class> testClass);
}

TestNGがインスタンス化する必要があるテストコンテキストとテストクラスのインスタンスが工場に渡されます.createModuleメソッドは、このテストクラスをインスタンス化する方法を知っているGuiceモジュールを返します.テストコンテキストを使用して、testngなどの環境に関する詳細を検索できます.xmlで指定したパラメータなど.親モジュールとguice-stageスイートパラメータを使用すると、より柔軟性とGuice機能が得られます.guice-stageでは、親注射器を作成するためのStageを選択できます.デフォルトはDEVELOPMENTです.その他の許容値はPRODUCTIONとTOOLです.これはtestです.xmlファイルで親モジュールを定義する方法:
<suite parent-module="com.example.SuiteParenModule" guice-stage="PRODUCTION">
suite>

指定されたスイートの場合、TestNGはこのモジュールを一度だけ作成します.また、このモジュールを使用して、テスト用のGuiceモジュールとモジュールファクトリ固有のインスタンスを取得し、各テストクラスにサブインジェクタを作成します.この方法では、親モジュールにすべての共通バインドを宣言したり、親モジュールに宣言されたバインドをモジュールおよびモジュールファクトリに注入したりできます.この機能の例です.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
package com.example;
 
public class ParentModule extends AbstractModule {
  @Override
  protected void conigure() {
    bind(MyService.class).toProvider(MyServiceProvider.class);
    bind(MyContext.class).to(MyContextImpl.class).in(Singleton.class);
  }
}

 
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
package com.example;
 
public class TestModule extends AbstractModule {
  private final MyContext myContext;
 
  @Inject
  TestModule(MyContext myContext) {
    this.myContext = myContext
  }
   
  @Override
  protected void configure() {
    bind(MySession.class).toInstance(myContext.getSession());
  }
}

 
<suite parent-module="com.example.ParentModule">
suite>

 
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
package com.example;
 
@Test
@Guice(modules = TestModule.class)
public class TestClass {
  @Inject
  MyService myService;
  @Inject
  MySession mySession;
   
  public void testServiceWithSession() {
    myService.serve(mySession);
  }
}

ご覧のように、ParentModuleはMyServiceクラスとMyContextクラスにバインドを宣言しています.次にコンストラクション関数注入を使用してMyContextをTestModuleクラスに注入し、このクラスはMySessionへのバインドも宣言します.次に、テストXMLファイルのparent-moduleをParentModuleクラスに設定し、TestModuleでの注入を有効にします.後でTestClassでは、*MyServices-バインドはParentModule*MySession-バインドはTestModuleから取得されます.この構成により、同じセッションインスタンスを使用してスイート内のすべてのテストを実行できるようになります.MyContextImplオブジェクトはスイートごとに1回しか作成されません.これにより、スイート内のすべてのテストに対して共通の環境状態を構成できます.
2.-リスニングメソッド呼び出し
リスナーIInvokedMethodListenerは、TestNGがテスト(@Testコメント)または構成(@Beforeまたは@Afterコメントのいずれかのコメント)メソッドを呼び出すたびに通知します.次のインタフェースを実装する必要があります.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public interface IInvokedMethodListener extends ITestNGListener {
  void beforeInvocation(IInvokedMethod method, ITestResult testResult);
  void afterInvocation(IInvokedMethod method, ITestResult testResult);
}

TestNGリスナーに関する部分に記載されているように、リスナーとして宣言します. 
3.-オーバーライドテスト方法
TestNGでは、テストメソッドの呼び出しを書き換え、スキップすることができます.1つの有用な例は、特定のセキュリティマネージャを使用してメソッドをテストする必要がある場合です.IHookableを実装するリスナーを提供することで、この目的を達成できます.
これはJAASの例です.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public class MyHook implements IHookable {
  public void run(final IHookCallBack icb, ITestResult testResult) {
    // Preferably initialized in a @Configuration method
    mySubject = authenticateWithJAAs();
    
    Subject.doAs(mySubject, new PrivilegedExceptionAction() {
      public Object run() {
        icb.callback(testResult);
      }
    };
  }
}

4.-変更キット(または)テスト
実行時にスイートxmlのスイート(または)テストラベルを変更するだけで、スイートファイルの内容を変更する必要がない場合があります.
1つの典型的な例は、既存のスイートファイルを使用して、「被験アプリケーション」で負荷テストをシミュレートしようとすることです.少なくとも、タグの内容を最終的に複数回コピーし、新しいスイートxmlファイルを作成して使用します.しかし、これはあまり規模がないようです.
TestNGでは、実行時にリスナーを介してスイートxmlファイルのスイート(または)テストラベルを変更できます.IAlterSuiteListenerを実装するリスナーを提供することで、この目的を達成できます.Listenerについては、Listenerセクションを参照してください.
これは、実行時にスイート名がどのように変更されるかを示す例です.
/**
 * @author   -  
 * 
 * Java       -09 - TestNG       
 *
 * 2019 11 8 
 */
public class AlterSuiteNameListener implements IAlterSuiteListener {
 
    @Override
    public void alter(List suites) {
        XmlSuite suite = suites.get(0);
        suite.setName(getClass().getSimpleName());
    }
}

このリスナーは、次のいずれかの方法で追加できます.
スイートxmlファイルのタグを使用します.@Listenersコメントを使用して、このリスナーを実行に追加することはできません.
5.-まとめ
さて、今日はTestNGの依存注入について、ここまで分かち合います.