コンテンツにスキップ

TestNG 包括的チートシート

TestNG 包括的チートシート

インストール

プラットフォーム/ツールインストール方法
MavenAdd to pom.xml:
<dependency>
  <groupId>org.testng</groupId>
  <artifactId>testng</artifactId>
  <version>7.8.0</version>
  <scope>test</scope>
</dependency>
GradleAdd to build.gradle:
testImplementation 'org.testng:testng:7.8.0'
Eclipse IDEヘルプ → Eclipse Marketplace → “TestNG” を検索 → インストール
IntelliJ IDEAデフォルトでバンドル(または ファイル → 設定 → プラグイン → マーケットプレイス → “TestNG”)
VS Codecode --install-extension vscjava.vscode-java-pack
code --install-extension testng.testng
Manual (Linux/macOS)wget https://repo1.maven.org/maven2/org/testng/testng/7.8.0/testng-7.8.0.jar
export CLASSPATH=$CLASSPATH:/path/to/testng-7.8.0.jar
Manual (Windows)Download JAR from Maven Central
set CLASSPATH=%CLASSPATH%;C:\path\to\testng-7.8.0.jar

コアアノテーション

アノテーション説明
@Testテストメソッドとしてメソッドをマークします
@Test(priority = 1)実行順序を設定します(数値が小さいものが先に実行されます)
@Test(description = "...")レポート用のテストに説明テキストを追加
@Test(timeOut = 5000)タイムアウト(ミリ秒)を超えた場合にテストに失敗します
@Test(expectedExceptions = Exception.class)特定の例外がスローされることを期待する
@Test(enabled = false)テストを無効化/スキップする
@Test(groups = {"smoke", "regression"})1つまたは複数のグループにテストを割り当てる
@Test(dependsOnMethods = {"testMethod"})指定されたメソッド完了後に実行されます
@Test(dependsOnGroups = {"smoke"})指定されたグループ内のすべてのテスト後に実行されます
@Test(alwaysRun = true)依存関係が失敗しても、テストを実行します
@Test(invocationCount = 3)テストを複数回実行
@Test(threadPoolSize = 5)並列スレッドで複数の呼び出しを実行
@BeforeMethodExecutes before each @Test method
@AfterMethodExecutes after each @Test method
@BeforeClassクラス内の任意のテストメソッドの前に1回実行されます
@AfterClassクラス内のすべてのテストメソッドの後に1回実行されます
@BeforeTestExecutes before any test method in <test> tag
@AfterTestExecutes after all test methods in <test> tag
@BeforeSuiteスイート内のすべてのテストの前に1回実行されます
@AfterSuiteスイート内のすべてのテストの後に1回実行されます
@BeforeGroups指定されたグループの最初のテストメソッドの前に実行されます
@AfterGroups指定されたグループの最後のテストメソッド後に実行されます
@DataProviderパラメータ化のためのメソッドをテストするデータを提供します
@ParametersInjects parameters from testng.xml into test methods
@Factoryテストインスタンスを動的に作成します
@Listenersテストクラスにカスタムリスナーをアタッチする

コマンドライン実行

コマンド説明
java -cp "classes:lib/*" org.testng.TestNG testng.xmlXML スイートファイルを使用してテストを実行する
java -cp "classes:lib/*" org.testng.TestNG -testclass com.example.MyTest特定のテストクラスを実行
java -cp "classes:lib/*" org.testng.TestNG -testclass Test1,Test2複数のテストクラス(カンマ区切り)を実行
java -cp "classes:lib/*" org.testng.TestNG -groups smoke testng.xml特定のグループからテストを実行
java -cp "classes:lib/*" org.testng.TestNG -excludegroups slow testng.xml実行から特定のグループを除外する
java -cp "classes:lib/*" org.testng.TestNG -d test-output testng.xmlレポートの出力ディレクトリを指定
java -cp "classes:lib/*" org.testng.TestNG -parallel methods -threadcount 5スレッド数で並列にテストを実行
java -cp "classes:lib/*" org.testng.TestNG -verbose 10 testng.xml詳細レベルを設定 (0-10、数値が高いほど詳細)
java -cp "classes:lib/*" org.testng.TestNG -methods MyTest.test1,MyTest.test2特定のテストメソッドを実行
java -cp "classes:lib/*" org.testng.TestNG -suitename "MySuite" -testname "MyTest"スイートとテストの名前をオーバーライド
java -cp "classes:lib/*" org.testng.TestNG -reporter org.testng.reporters.EmailableReporter特定のレポーターを使用する
java -cp "classes:lib/*" org.testng.TestNG -listener com.example.MyListenerカスタムリスナーを追加

Mavenコマンド

コマンド説明
mvn testすべてのテストを実行
mvn test -Dtest=MyTestClass特定のテストクラスを実行
mvn test -Dtest=MyTestClass#testMethod特定のテストメソッドを実行
mvn test -Dtest=MyTestClass#test*パターンに一致するテストメソッドを実行
mvn test -DsuiteXmlFile=smoke-tests.xml特定のスイートXMLファイルを実行
mvn test -Dgroups=smoke,regression特定のテストグループを実行
mvn test -DexcludedGroups=slow特定のテストグループを除外
mvn test -Denvironment=staging -Dbrowser=chromeシステムプロパティをテストに渡す
mvn test -DskipTestsテスト実行をスキップ
mvn test -Dmaven.test.failure.ignore=trueテストが失敗しても、ビルドを継続する
mvn test -Dparallel=methods -DthreadCount=4テストを並列で実行
mvn clean test以前のビルドをクリーンにし、テストを実行する
mvn test -Xデバッグ出力でテストを実行
mvn surefire-report:reportHTMLテストレポートを生成

Gradleコマンド

コマンド説明
gradle testすべてのテストを実行
gradle test --tests MyTestClass特定のテストクラスを実行
gradle test --tests MyTestClass.testMethod特定のテストメソッドを実行
gradle test --tests *IntegrationTestパターンに一致するテストを実行
gradle test --tests MyTestClass --tests OtherTest複数のテストクラスを実行する
gradle test -Denvironment=stagingシステムプロパティを渡す
gradle clean testテストをクリーンにして実行する
gradle test --info詳細なログ出力で実行
gradle test --debugデバッグレベルのログで実行
gradle test --rerun-tasks最新の状態でも強制的に再実行
gradle test --continueテスト失敗後も実行を継続する
gradle test --fail-fast最初のテスト失敗で実行を停止

アサーションメソッド

メソッド説明
Assert.assertEquals(actual, expected)2つの値が等しいことを確認する
Assert.assertEquals(actual, expected, "message")カスタム失敗メッセージを使用したアサート
Assert.assertNotEquals(actual, expected)2つの値が等しくないことを確認する
Assert.assertTrue(condition)条件が真であることを確認する
Assert.assertFalse(condition)条件が偽であることを確認する
Assert.assertNull(object)オブジェクトが null であることを確認する
Assert.assertNotNull(object)オブジェクトが null でないことを確認する
Assert.assertSame(actual, expected)同じオブジェクト参照を確認する
Assert.assertNotSame(actual, expected)異なるオブジェクト参照を検証する
Assert.fail("message")テストを明示的に失敗させる
Assert.assertThrows(Exception.class, () -> {...})例外がスローされることを確認する
Assert.expectThrows(Exception.class, () -> {...})assertThrows と同じ(エイリアス)

データプロバイダ

パターン説明
@DataProvider(name = "testData")データプロバイダーメソッドを定義する
@Test(dataProvider = "testData")テストでデータプロバイダーを使用する
@DataProvider(parallel = true)データプロバイダの反復処理を並列に実行する
Object[][] dataProvider()テストデータの2D配列を返す
Iterator<Object[]> dataProvider()大規模なデータセットのためのイテレータを返す
@DataProvider(indices = {0, 2, 4})特定のデータセットインデックスのみを実行

データプロバイダの例

@DataProvider(name = "loginData")
public Object[][] getLoginData() {
    return new Object[][] {
        {"user1", "pass1", true},
        {"user2", "pass2", false},
        {"user3", "pass3", true}
    };
}

@Test(dataProvider = "loginData")
public void testLogin(String username, String password, boolean expected) {
    boolean result = login(username, password);
    Assert.assertEquals(result, expected);
}

TestNG XMLコンフィグレーション

基本スイート設定

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Test Suite" parallel="methods" thread-count="5" verbose="1">
    
    <!-- Suite-level parameters -->
    <parameter name="browser" value="chrome"/>
    <parameter name="environment" value="staging"/>
    
    <!-- Define test groups -->
    <test name="Smoke Tests">
        <groups>
            <run>
                <include name="smoke"/>
                <exclude name="slow"/>
            </run>
        </groups>
        
        <!-- Specify test classes -->
        <classes>
            <class name="com.example.LoginTest"/>
            <class name="com.example.SearchTest">
                <!-- Include specific methods -->
                <methods>
                    <include name="testBasicSearch"/>
                    <include name="testAdvancedSearch"/>
                </methods>
            </class>
        </classes>
    </test>
    
    <!-- Another test configuration -->
    <test name="Regression Tests">
        <packages>
            <package name="com.example.regression.*"/>
        </packages>
    </test>
    
    <!-- Listeners -->
    <listeners>
        <listener class-name="com.example.CustomListener"/>
    </listeners>
</suite>

並列実行設定

<!-- Parallel at suite level -->
<suite name="Parallel Suite" parallel="tests" thread-count="3">
    <test name="Test1">...</test>
    <test name="Test2">...</test>
</suite>

<!-- Parallel options: methods, tests, classes, instances -->

Maven Surefireプラグイン設定

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <!-- Specify suite files -->
                <suiteXmlFiles>
                    <suiteXmlFile>testng.xml</suiteXmlFile>
                    <suiteXmlFile>smoke-tests.xml</suiteXmlFile>
                </suiteXmlFiles>
                
                <!-- Run specific groups -->
                <groups>smoke,regression</groups>
                <excludedGroups>slow,manual</excludedGroups>
                
                <!-- Parallel execution -->
                <parallel>methods</parallel>
                <threadCount>5</threadCount>
                
                <!-- System properties -->
                <systemPropertyVariables>
                    <browser>chrome</browser>
                    <environment>staging</environment>
                </systemPropertyVariables>
                
                <!-- Continue on failures -->
                <testFailureIgnore>false</testFailureIgnore>
            </configuration>
        </plugin>
    </plugins>
</build>

Gradleテスト設定

test {
    useTestNG() {
        // Suite files
        suites 'src/test/resources/testng.xml'
        
        // Include/exclude groups
        includeGroups 'smoke', 'regression'
        excludeGroups 'slow'
        
        // Parallel execution
        parallel = 'methods'
        threadCount = 5
        
        // Preserve order
        preserveOrder = true
        
        // Group by instances
        groupByInstances = true
    }
    
    // System properties
    systemProperty 'browser', 'chrome'
    systemProperty 'environment', 'staging'
    
    // Test output
    testLogging {
        events "passed", "skipped", "failed"
        exceptionFormat "full"
    }
}

一般的なユースケース

ユースケース1: セットアップとティアダウンを含む基本的なテストクラス

import org.testng.annotations.*;
import org.testng.Assert;

public class UserManagementTest {
    
    private DatabaseConnection db;
    private UserService userService;
    
    @BeforeClass
    public void setupClass() {
        // Initialize database connection once for all tests
        db = new DatabaseConnection("jdbc:mysql://localhost:3306/testdb");
        db.connect();
    }
    
    @BeforeMethod
    public void setupMethod() {
        // Create fresh service instance before each test
        userService = new UserService(db);
    }
    
    @Test(priority = 1, groups = {"smoke"})
    public void testCreateUser() {
        User user = userService.createUser("john@example.com", "John Doe");
        Assert.assertNotNull(user.getId());
        Assert.assertEquals(user.getEmail(), "john@example.com");
    }
    
    @Test(priority = 2, dependsOnMethods = {"testCreateUser"})
    public void testFindUser() {
        User user = userService.findByEmail("john@example.com");
        Assert.assertNotNull(user);
        Assert.assertEquals(user.getName(), "John Doe");
    }
    
    @AfterMethod
    public void cleanupMethod() {
        // Clean up test data after each test
        userService.deleteAllUsers();
    }
    
    @AfterClass
    public void cleanupClass() {
        // Close database connection after all tests
        db.disconnect();
    }
}

ユースケース2: データプロバイダを使用したデータ駆動テスト

import org.testng.annotations.*;
import org.testng.Assert;

public class LoginTest {
    
    private LoginPage loginPage;
    
    @BeforeMethod
    public void setup() {
        loginPage = new LoginPage();
        loginPage.open();
    }
    
    @DataProvider(name = "loginCredentials")
    public Object[][] getLoginData() {
        return new Object[][] {
            {"valid@user.com", "ValidPass123", true, "Dashboard"},
            {"invalid@user.com", "WrongPass", false, "Invalid credentials"},
            {"", "password", false, "Email is required"},
            {"user@test.com", "", false, "Password is required"},
            {"admin@test.com", "AdminPass!", true, "Admin Panel"}
        };
    }
    
    @Test(dataProvider = "loginCredentials")
    public void testLogin(String email, String password, 
                         boolean shouldSucceed, String expectedMessage) {
        loginPage.enterEmail(email);
        loginPage.enterPassword(password);
        loginPage.clickLogin();
        
        if (shouldSucceed) {
            Assert.assertTrue(loginPage.isLoggedIn());
            Assert.assertEquals(loginPage.getPageTitle(), expectedMessage);
        } else {
            Assert.assertTrue(loginPage.hasError());
            Assert.assertTrue(loginPage.getErrorMessage().contains(expectedMessage));
        }
    }
    
    @AfterMethod
    public void teardown() {
        loginPage.close();
    }
}

ユースケース3: グループを使用した並列テスト実行

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Parallel Test Suite" parallel="tests" thread-count="3">
    
    <test name="Chrome Tests" parallel="methods" thread-count="2">
        <parameter name="browser" value="chrome"/>
        <groups>
            <run>
                <include name="smoke"/>
            </run>
        </groups>
        <classes>
            <class name="com.example.tests.HomePageTest"/>
            <class name="com.example.tests.SearchTest"/>
        </classes>
    </test>
    
    <test name="Firefox Tests" parallel="methods" thread-count="2">
        <parameter name="browser" value="firefox"/>
        <groups>
            <run>
                <include name="smoke"/>
            </run>
        </groups>
        <classes>
            <class name="com.example.tests.HomePageTest"/>
            <class name="com.example.tests.SearchTest"/>
        </classes>
    </test>
    
    <test name="API Tests" parallel="classes" thread-count="3">
        <groups>
            <run>
                <include name="api"/>
            </run>
        </groups>
        <packages>
            <package name="com.example.api.*"/>
        </packages>
    </test>
</suite>
// Test class using parameters
public class CrossBrowserTest {
    
    private WebDriver driver;
    
    @Parameters({"browser"})
    @BeforeMethod
    public void setup(String browser) {
        if (browser.equalsIgnoreCase("chrome")) {
            driver = new ChromeDriver();
        } else if (browser.equalsIgnoreCase("firefox")) {
            driver = new FirefoxDriver();
        }
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
    }
    
    @Test(groups = {"smoke"})
    public void testHomePage() {
        driver.get("https://example.com");
        Assert.assertEquals(driver.getTitle(), "Example Domain");
    }
    
    @AfterMethod
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

ユースケース4: リトライロジックを使用したAPIテスト

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

// Retry analyzer for flaky tests
public class RetryAnalyzer implements IRetryAnalyzer {
    private int retryCount = 0;
    private static final int MAX_RETRY = 3;
    
    @Override
    public boolean retry(ITestResult result) {
        if (retryCount < MAX_RETRY) {
            retryCount++;
            return true;
        }
        return false;
    }
}

// API Test class
public class APITest {
    
    private RestClient client;
    
    @BeforeClass
    public void setup() {
        client = new RestClient("https://api.example.com");
    }
    
    @Test(groups = {"api"}, retryAnalyzer = RetryAnalyzer.class)
    public void testGetUser() {
        Response response = client.get("/users/1");
        Assert.assertEquals(response.getStatusCode(), 200);
        Assert.assertNotNull(response.jsonPath().getString("name"));
    }
    
    @Test(groups = {"api"}, dependsOnMethods = {"testGetUser"})
    public void testCreateUser() {
        String payload = "{\"name\":\"John\",\"email\":\"john@test.com\"}";
        Response response = client.post("/users", payload);
        Assert.assertEquals(response.getStatusCode(), 201);
    }
    
    @Test(groups = {"api"}, timeOut = 5000)
    public void testPerformance() {
        long startTime = System.currentTimeMillis();
        Response response = client.get("/users");
        long endTime = System.currentTimeMillis();
        
        Assert.assertEquals(response.getStatusCode(), 200);
        Assert.assertTrue((endTime - startTime) < 3000, 
            "API response time exceeded 3 seconds");
    }
}

ユースケース5: カスタムリスナーとレポーティング

import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.ITestContext;

public class CustomTestListener implements ITestListener {
    
    @Override
    public void onTestStart(ITestResult result) {
        System.out.println("Starting test: " + result.getName());
    }
    
    @Override
    public void onTestSuccess(ITestResult result) {
        System.out.println("Test passed: " + result.getName());
    }
    
    @Override
    public void onTestFailure(ITestResult result) {
        System.out.println("Test failed: " + result.getName());
        // Take screenshot, log error, etc.
        captureScreenshot(result.getName());
    }
    
    @Override
    public void onTestSkipped(ITestResult result) {
        System.out.println("Test skipped: " + result.getName());
    }
    
    @Override
    public void onFinish(ITestContext context) {
        System.out.println("Total tests run: " + context.getAllTestMethods().length);
        System.out.println("Passed: " + context.getPassedTests().size());
        System.out.println("Failed: " + context.getFailedTests().size());
        System.out.println("Skipped: " + context.getSkippedTests().size());
    }
    
    private void captureScreenshot(String testName) {
        // Screenshot logic here
    }
}

// Using the listener
@Listeners(CustomTestListener.class)
public class MyTest {
    
    @Test
    public void testExample() {
        Assert.assertTrue(true);
    }
}

ベストプラクティス

  • 意味のあるテスト名を使用する: テストを明確に名付け、何を検証するかを説明する(例:testUserCanLoginWithValidCredentialsの代わりに

Would you like me to provide the specific translations for the numbered placeholders?test1)

  • Leverage groups effectively: Organize tests into logical groups (smoke, regression, api, ui) to run subsets of tests based on context and save execution time

  • Implement proper setup and teardown: Use @BeforeMethod/@AfterMethod for test-level setup and @BeforeClass/@AfterClass for expensive operations like database connections

  • Make tests independent: Each test should be self-contained and not rely on execution order or shared state. Use dependsOnMethods sparingly and only when logical dependency exists

  • Use DataProviders for test data: Separate test data from