Parameterizing on TestNG

Dahun Yoo·2022년 10월 30일
0

Introduce to TestNG

목록 보기
4/5

TestNG에서 테스트 메소드들에 데이터를 넘기기 위한 방법들을 기재해봅니다.


Parameterizing on TestNG

xml file

파라미터로 이용해야할 데이터의 갯수가 적다면, xml파일에 직접 기재할 수도 있습니다.
어떠한 주소나, API 키값 등 대부분의 테스트 메소드에서 사용될 수 있는 공통적인 데이터들도 작성하면 좋습니다.

<parameter name=“URL” value=“https://www.naver.com”></parameter>

이렇게 name과 value가 있는 형식으로, xml파일 내에서 parameter 태그를 선언해서 사용할 수 있습니다. test태그의 밖이냐 안이냐에 따라 global, local 변수처럼 사용할 수 있습니다.

<suite name=“All Test Suite”>
    <parameter name=“URL” value=“https://www.naver.com”></parameter>
    <test verbose="2" preserve-order="true"
          name="TestNG1">
        <classes> <!-- module -->
            <class name="section18.RunningTestcases"/>
            <class name="section18.AnnotationTest"/>
        </classes>
    </test>

위 내용은 suite 단계에서 parameter를 선언하고 있으므로, suite 하위에 선언된 test태그 및, 그 test태그 내부에서 사용되는 테스트 파일들이라면, 어디서든 해당 파라미터를 사용할 수 있습니다.

override parameter

<suite name="All Test Suite">
    <parameter name="URL" value="https://www.naver.com"/>
    <test verbose="2" preserve-order="true" name="Android">
        <parameter name="URL" value="https://m.naver.com"/>
        <groups>
            <run>
                <include name="Android"/>
            </run>
        </groups>
        <classes>
            <class name="priorityExecute.WebLoginTest"/>
            <class name="priorityExecute.AppLoginTest"/>
        </classes>
    </test>
.
.
.

위 내용처럼, suite레벨에서의 URL 파라미터가 선언되어있지만, 하위 test태그 아래에서 다시 URL 파라미터가 선언되어있다면, 해당 테스트가 실행될때에는 parameter가 override되어 사용됩니다.

같은 URL 파라미터이지만 Android 테스트의 경우에만 모바일 주소가 사용되고 있고, Web인 경우에는 웹주소가 사용되고 있는 것을 알 수 있습니다.


how to using parameter on test method

@Parameters({"URL"})
@Test(groups = {"web"})
public void pcNaverWebLogin(String url) {
    System.out.println(url);

}

@Parameter 어노테이션을 이용해서, xml파일에 선언한 parameter태그의 name 값을 기재해줍니다.

만약, 여러개의 파라미터가 필요하다면, 컴마로 구분해서 선언해줍니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite">
    <parameter name="URL" value="https://www.naver.com"/>
    <test verbose="2" preserve-order="true" name="Android">
        <parameter name="URL" value="https://m.naver.com"/>

        <groups>
            <run>
                <include name="Android"/>
            </run>
        </groups>
        <classes>
            <class name="priorityExecute.WebLoginTest"/>
            <class name="priorityExecute.AppLoginTest"/>
        </classes>
    </test>
    <test verbose="2" preserve-order="true" name="web">
        <parameter name="password" value="123"/>
        <groups>
            <run>
                <include name="web"/>
            </run>
        </groups>
        <classes>
            <class name="priorityExecute.WebLoginTest"/>
            <class name="priorityExecute.AppLoginTest"/>
        </classes>
    </test>
</suite>
@Parameters({"URL", "password"})
@Test(groups = {"web"})
public void pcNaverWebLogin(String url, String password) {
    System.out.println(url + ", " + password);
}

위 코드는, suite 레벨에서 선언된 URL 파라미터와, web test 레벨에서 선언된 password 파라미터를 사용합니다.

xml로 관리하게 되면 파라미터를 알기 쉽게 원하는 레벨에서 관리할 수가 있습니다.
그러나 사용하는 파라미터가 많아지게되면 어떻게 해야할까요?

예를 들어 로그인 아이디와 패스워드를 수십개를 바꾸어가며 로그인을 하는 테스트케이스를 확인하려면, xml에 모든 패턴을 기재하려면 엄청 관리하기가 어려워질 것입니다.

@DataProvider

TestNG에서는 DataProvider 어노테이션을 이용해 데이터를 전달할 수 있도록 하고 있습니다.

@DataProvider
public Object[][] getInternalAPIData() {
    Object[][] data = new Object[2][2];

    data[0][0] = "username1";
    data[0][1] = "password1";

    data[1][0] = "username2";
    data[1][1] = "password1";

    return data;

}
@Test(dataProvider = "getInternalAPIData")
public void internalApiLoginUsingInternalData(String username, String password)
{
    System.out.println("username : "+ username + ", password : "+ password);
}

사용할 때는 @Test 어노테이션에서 dataProvider 옵션을 설정하고, 데이터를 주입해주는 메소드의 이름을 기재해줍니다.

이렇게 한다면, 주입하는 데이터의 갯수만큼 해당 메소드를 반복해서 실행하게 됩니다. 위 코드의 예시라면 데이터가 2개 행을 가지고 있으므로, 테스트 메소드는 2회를 반복실행하며 모든 데이터들을 실행합니다.

DataProvider 메소드는, 별도의 이름을 지정해줄 수도 있습니다.
이 경우에는 지정한 이름으로 호출해야합니다.

@DataProvider(name = "getInternalAPIData")
public Object[][] getData() {
    Object[][] data = new Object[2][2];

    data[0][0] = "username1";
    data[0][1] = "password1";

    data[1][0] = "username2";
    data[1][1] = "password2";

    return data;
}

return type

DataProvider는 아래의 타입에 대해 리턴을 지원합니다.

- Object[] 
- Ojbect[][]
- Iterator<Object>
- Iterator<Object[]>

최대 2차원배열까지 지원합니다. 객체의 타입은 Object로 기재하고는 있지만, 사실 모든 객체에 대해 대응합니다.

어떠한 자료구조를 이용한다면, 리턴할 때에 Iterator 타입을 리턴하도록 합니다.

public Iterator<String> getIteratorData() {
    List<String> data = new ArrayList<String>();

    data.add("username1");
    data.add("password1");

    data.add("username2");
    data.add("password2");

    return data.iterator();
}

indice

배열로 된 데이터에서 특정 데이터만 넘기고자 한다면, indice 옵션을 사용할 수도 있습니다.

@DataProvider(name = "getInternalAPIData", indices = {1})
public String[][] getData() {
    String[][] data = new String[2][2];

    data[0][0] = "username1";
    data[0][1] = "password1";

    data[1][0] = "username2";
    data[1][1] = "password2";

    return data;
}

indices 에는 정수형 값을 지정해주며, 이 의미는 곧 배열의 특정 인덱스의 데이터만 넘겨주겠다~ 라는 의미로 사용합니다.

DataProvider class

기본적으로, DataProvider는, DataProvider를 사용하는 테스트 메소드와 같은 클래스 내부에 위치해야합니다.

만약 DataProvider만 별도의 파일로 관리하고 이것을 사용하자면 아래처럼 사용하면 됩니다.

@Test(dataProvider = "getInternalAPIData", dataProviderClass = DataBuilder.class)
public void internalApiLoginUsingInternalData(String username, String password)
{
    System.out.println("username : "+ username + ", password : "+ password);
}

dataProviderClass 에, DataProvider 메소드들을 선언한 클래스의 정보를 지정해줍니다. dataProvider 에는 사용하고자 하는 DataProvider 메소드의 이름을 기재해주면 됩니다.

이렇게 하면 데이터주입을 위한 여러 메소드들을 관리할 수 있습니다.

profile
QA Engineer

0개의 댓글