Junit을 사용하여 테스트를 진행하고, 결과 중 fail된 case만 따로 다시 수행시켜보는 방법 보다는

fail된 case를 바로 더 돌리도록 해서 그 이후에 결과를 확인하는 것이 더 좋을 때가 있다.


이럴 때는 TestRule을 이용해서 JUnit Retry를 구현하는 방법을 사용한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import org.junit.rules.TestRule; 
import org.junit.runner.Description; 
import org.junit.runners.model.Statement; 
 
public class JUnitRetry implements TestRule { 
 
    private int retryCount; 
 
    public JUnitRetry(int retryCount) { 
        this.retryCount = retryCount; 
    } 
 
    @Override
    public Statement apply(Statement base, Description description) { 
        return statement(base, description); 
    } 
 
    private Statement statement(final Statement base, final Description description) { 
        return new Statement() { 
            @Override
            public void evaluate() throws Throwable { 
                Throwable caughtThrowable = null
 
                // implement retry logic here 
                for (int i = 0; i < retryCount; i++) { 
                    try { 
                        base.evaluate(); 
                        return
                    } catch (Throwable t) { 
                        caughtThrowable = t; 
                        System.err.println(description.getDisplayName() + ": run " + (i+1+ " failed"); 
                    } 
                } 
                System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); 
                throw caughtThrowable; 
            } 
        }; 
    } 
}
cs

위와 같이 JUnitRetry 클래스를 만들어 놓고, 테스트코드에서는 Rule을 사용하여 Retry 를 몇번 할지 횟수만 지정하고 사용하면 된다. 

1
2
@Rule
public JUnitRetry retry = new JUnitRetry(2);
cs


Windows에서 Selenium으로 UI자동화 진행하다보면, chromedriver.exe가 남아있어서 브라우저가 기동이 안될 경우가 있다.

driver.quit()을 꼼꼼히 호출해도 남아있는 경우가 있는데, 

jenkins 에서 pre-build 단계나, test진행 전 단계에 taskkill을 이용하는 것이 좋다.


windows batch command 수행 (jenkins pre-build)

taskkill /f /fi "pid gt 0" /im chromedriver.exe


Java code에서 (BeforeClass)

Runtime.getRuntime().exec("taskkill /f /fi /im chromedriver.exe");


selenide는 driver.close()나 wait() 등을 알아서 진행해주기 때문에 좀 더 스마트한 UI자동화 도구이다.

selenium은 사실 webdriver를 통한 브라우저 제어 도구에 좀 더 가깝다. 


selenide에서 chrome webdriver를 세팅할때, 

  • selenide.browser 
  • webdriver.chrome.driver
위 두 프로퍼티를 설정하면, 알아서 UI브라우저 관리를 해주는데, 모바일 에뮬레이션을 하려고 할때는 아래와 같이 진행하면 된다.

단점은 모바일 에뮬레이션을 하면, 직접 browser(webdriver)를 close()를 해줘야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SelenideMWChromeTest {
 
    @Before
    public void setUp() {        
        Map<StringString> mobileEmulation = new HashMap<>();
        mobileEmulation.put("deviceName""Nexus 5");
 
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setExperimentalOption("mobileEmulation", mobileEmulation);
 
        WebDriver driver = new ChromeDriver(chromeOptions);
 
        WebDriverRunner.setWebDriver(driver);
        Configuration.browser = WebDriverRunner.class.getName();    
    }
 
    @After
    public void tearDown() throws Exception{
         close();
    }
 
    @Test
    public void testStep() throws Exception{
        ... 중략 ...
cs



junit 4.x에서 csv 파일을 읽어서 data driven testing을 구현하는 방법.

junit 5에는 @CsvFileSource 라는게 이미 있지만, junit 4.x 에는 없어서 구현을 해야 한다.

근데, 구글링 해보니, JUnitParams라는 아주 편리한 라이브러리가 있네.


구현 방법도 쉽다.

우선 maven pom.xml에 dependancy 추가하고

<dependency>
    <groupId>pl.pragmatists</groupId>
    <artifactId>JUnitParams</artifactId>
    <version>1.1.1</version>
    <scope>test</scope>
</dependency>
cs


테스트 코드에는 아래와 같이 구현하면 끝.

간단하고 편하네.


1
2
3
4
5
6
7
8
9
10
import junitparams.*
 
@RunWith(JUnitParamsRunner.class)    
public class SamplesOfUsageTest {
 
    @Test
    @FileParameters("classpath:test.csv")
    public void loadParamsFromClasspath(int age, String name) { 
        .. 테스트 코드 작성 ..
    }
cs


csv 파일 말고, 다른 방법으로 하는 링크된 샘플코드에 많이 나와 있으니, 생략한다. 


junit을 활용한 테스트 자동화에 익숙하다보니, api테스트 자동화 한다고 하면 request, response 동작을 위한 util 및 json / xml parser 등을 모두 구현해서 사용했었는데, 

그동안 왜 그랬나 싶을 정도로,, Rest-Assured는 잘 만들어진 api 테스트 자동화 도구이다. 

링크 : http://rest-assured.io/


환경 구성이나, 손 쉬운 사용법은 위 링크의 User Guide 문서를 참고하면 사용할 수 있다.

그래도 자동화 하면, 쉬운 반복 수행 및 결과 리포팅이 중요하니, 아래와 같이 구성하자.


  • 빌드 도구 : maven (or gradle)
  • 테스트 도구 : junit + rest-assured
  • 리포트 : extent-report
  • 통합 : Jenkins

환경 구성 (maven)

  <dependencies>
     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
     </dependency>
     <dependency>
         <groupId>org.hamcrest</groupId>
         <artifactId>hamcrest-all</artifactId>
         <version>1.3</version>
     </dependency>
     <dependency>
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
         <version>2.6.2</version>
     </dependency>
     <dependency>
          <groupId>io.rest-assured</groupId>
          <artifactId>rest-assured</artifactId>
          <version>3.0.2</version>
     </dependency>
     <dependency>
         <groupId>io.rest-assured</groupId>
         <artifactId>json-path</artifactId>
         <version>3.0.2</version>
     </dependency>
     <dependency>
         <groupId>io.rest-assured</groupId>
         <artifactId>xml-path</artifactId>
         <version>3.0.2</version>
     </dependency>        
     <dependency>
         <groupId>com.aventstack</groupId>
         <artifactId>extentreports</artifactId>
         <version>3.0.1</version>
     </dependency>
  </dependencies>
cs

샘플 테스트 코드 예제 

1
2
3
4
5
6
7
8
given()
    .header("Cookie""Cookie-Value")
    .contentType("application/x-www-form-urlencoded")
    .body("Body Message")
.when()
    .post("http://www.naver.com/openapi/apitest?method=abcde")
.then()
    .statusCode(200);
cs

Extent-Report 세팅

Jenkins 연동

  • Maven Project 생성 후  > Build Step에 mvn clean test 정도만 추가하면 완료
  • html publisher plugin설정 후, 생성된 extent report 파일을 설정해주면 끝
  • html report에 CSS가 jenkins 권한 등의 문제로 수행이 안된다면, 
    • 젠킨스 관리 > Script console 에서 아래 명령어를 넣어준다.
  • System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

api 테스트 자동화를 Java 환경에서 진행한다면, rest-assured는 진짜 적극 검토해볼만하다~  좋다~



지금은 API 테스트를 진행하라고 하면 rest-assured를 사용하기 때문에 다른 도구 사용할 일이 없지만

그래도 api testing 도구라고 하면 제일 많이 사용되는 도구가 뭐냐고 하면 SoapUI라고 말할 것 같다. 

이전에 SoapUI를 업무에 잠시 활용했을 때 나름 정리해두었던 내용을 여기에 다시 게시한다.

기본적인 사용법은 여기저기에 더 잘 정리되어 있으니, 생략하고.. tip 위주로..


Property 제어

  • 프로퍼티는 동적으로 변경되는 값, 자주 변경되어야 하는 값을 처리할 때 사용하고, 가급적 프로젝트 레벨(혹은 Suite레벨)로 관리하자.
    • 예) Endpoint URL, Username, MDN 등
  • 프로퍼티 제어는 Groovy Script를 활용하거나 Property Transfer 등을 활용한다

Assertion


(1) XPath Assertion
  • xml형식의 response message 중 단순 string추출이 아닌 특정한 형식의 값을 추출해낼 수 있는 방법으로 xpath 를 사용한다.
  • xml syntax 참고 : http://www.w3schools.com/xpath/xpath_syntax.asp
  • SoapUI에서는 xpath문법을 그대로 사용하면 동작하지 않는다. 아래 예제를 참고하여 작성하기 바란다.
    • xml response의 namespace값을 꼭 사용해야 한다.

    • expression부분에 하기와 같이 작성한다. 하기 예제는 response message중 첫번째로 보이는 spotCode의 value값을 가져온다.

      declare namespace ns1="http://www.naver.com"; 
      //ns1:spotCode[1]
(2) Regular Expression Assertion
  • Contains/NotContains 의 Assertion에 RegularExpression을 사용하여 적용할 수 있다. 이를 사용하면, 특정 string값이 아닌 원하는 형태의 문장을 비교할 수 있다.
  • Regular Expression 연습하기 좋은 사이트 url : http://www.regerx.com
  • SoapUI에서는 Regular Expression 문법을 그대로 사용하면 동작하지 않는다. 아래 예제를 참고하여 작성하기 바란다.
    •  response message가 json형식일때를 예로 들어, code값이 4만에서 5만번 사이의 숫자가 포함되는 조건을 추가하기 원한다면,

    • Contains/Not Contains Assertion에 use token as Regular Expression 체크박스를 체크하고, Content박스에 하기의 예와 같이 입력한다.

      (?s).*"code": "[4,5]\d{4}".*

(3) Script Assertion

Groovy Script

  • Javascript를 수행해야 하거나, Property를 제어하고자 할 때 많이 사용한다. 
  • Property 수행예제, javascript 실행 예제, cookie 예제를 하나씩 정리한다.

(1) Property 수행 예제

    • 참고 : https://www.soapui.org/scripting-properties/tips-tricks.html#0-1-how-to-get-and-set-properties-from-groovy
    • // get properties from testCase, testSuite and project
      def testCaseProperty = testRunner.testCase.getPropertyValue( "MyProp" )
      def testSuiteProperty = testRunner.testCase.testSuite.getPropertyValue( "MyProp" )
      def projectProperty = testRunner.testCase.testSuite.project.getPropertyValue( "MyProp" )
      def globalProperty = com.eviware.soapui.SoapUI.globalProperties.getPropertyValue( "MyProp" )
       
      // setting values is equally straigh forward
      testRunner.testCase.setPropertyValue( "MyProp", someValue )
      testRunner.testCase.testSuite.setPropertyValue( "MyProp", someValue )
      testRunner.testCase.testSuite.project.setPropertyValue( "MyProp", someValue )
      com.eviware.soapui.SoapUI.globalProperties.setPropertyValue( "MyProp", someValue )

(2) JavaScript 실행 예제

  • import javax.script.*
       
    // 기본으로 제공되는 JS엔진 사용
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript")
    Invocable invocable = (Invocable) engine;     // JS 안의 메소드를 호출하는 인터페이스
      
    // JS loginName 을 파라미터로 넣어 호출하기 위한 함수를 만들어준다.
    def rsaFile = new URL("https://www.domain.com/encrypt.js").getText();
    rsaFile += """
    function fireEncrypt(str){
        return rsa.encrypt(str);
    };
    """;
    // 넣지 않으면 navigator가 없어 에러가 남.
    engine.put("navigator", "");
    engine.eval(rsaFile);
    def loginName = testRunner.testCase.testSuite.project.getPropertyValue("loginName");    // testSuite 에 설정한 property 를 읽어옴
    def encryptedLoginName = invocable.invokeFunction("fireEncrypt", loginName);
     
    testRunner.testCase.testSuite.project.setPropertyValue("encryptedLoginName",encryptedLoginName);      // testSuite 에 property 를 설정

(3) Cookie 설정 예제

  • import com.eviware.soapui.model.iface.SubmitContext
    import org.apache.http.client.protocol.ClientContext
    import org.apache.http.impl.cookie.BasicClientCookie
       
    // 현재 Case 가 실행되는 Context 를 받아와 여기에 저장한다. 그래서 이 Step 만 따로 실행하기는 안됨
    def httpContext = context.getProperties().getProperties().get(SubmitContext.HTTP_STATE_PROPERTY)
      
    def cookieStore = httpContext.getAttribute(ClientContext.COOKIE_STORE)
    def cookies = cookieStore.getCookies()
       
    // 쿠키에 세팅할 값.
    def sampleCookie = new BasicClientCookie("sample","sampleData");
    pcidCookie.setDomain(".naver.com")
      
    cookieStore.addCookie(sampleCookie)

Reporting


Jenkins 연동하기

1. 준비하기

  • jenkins에 아래와 같은 plugin이 설치되어 있어야 한다.

    • junit attachments plugin

    • junit plugin

    • git plugin

    • svn plugin
  • jenkins가 구동되는 장비에 soapUI가 설치되어 있어야 한다.

2. 수행하기

(0) Jenkins에서 프로젝트(new jobs) 생성 후..

(1) 소스(script) 코드 관리 부분 설정

    소스(soapui script)를 버전관리시스템(리파지토리, 현재 bitbucket)에서 가져오도록 설정

(2) Build 부분 설정

  • execute shell을 선택

    • command입력박스에 아래와 같이 입력 (SoapUI 의 TestRunner 수행을 위한 CommandLine 명령어를 넣어준다)

export JAVA_HOME=/app/jdk1.7.0_80; SOAPUI_HOME=/home/SoapUI-5.2.1; export SOAPUI_HOME; export PATH=$JAVA_HOME/bin:$PATH; export WORKSPACE=$WORKSPACE/MyWorkspace; rm -rf $WORKSPACE/report/JReport/*.xml; $SOAPUI_HOME/bin/testrunner.sh -a -j -I -f$WORKSPACE/report/JReport -PEndpoint=www.naver.com $WORKSPACE/test_api_project.xml

  • workspace는 soapui스크립트가 존재하는 곳을 지정하는 것이 좋음. 
  • -f 옵션은 결과파일 위치 지정, -P옵션은 스크립트 수행에 필요한 파라미터입력
  • 수행 전 기존 결과파일은 삭제하는 것이 좋음. 

(3)  빌드후 조치 부분 설정

  •  publish junit test result report 선택

    • Test report XMLs :  MyWorkspace/report/JReport/*.xml

    • Additional test report features 체크박스 체크.


+ Recent posts