mac을 쓰다보면, .DS_Store파일이 생기게 된다.

Mac의 메타정보를 저장하는 파일이라고 하는데 없어도 상관없고, 

일일이 지우는 것도 귀찮으니, 아예 생성하지 않도록 설정할 수 있다.

 

터미널에서 아래와 같이 입력한 뒤, 재시작한다.

defaults write com.apple.desktopservices DSDontWriteNetworkStores true

 

참고 : https://support.apple.com/en-us/HT1629

1
2
3
4
    static void waitForLoad(WebDriver driver) {
        new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
                ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
    }
cs


awk

  • 특정 패턴의 문자들을 원하는 포맷으로 변경하는 명령어
  • 사용법
    • awk [-F 구분자] [-f 파일명] ["patten {action}"] [처리할 file명]
  • 사용예
    • awk -F : "{print $1, $6}" ./text.txt
      • text.txt 파일에서 ":" 구분자를 이용하여 1번째와 6번째 필드를 프린트하라.
    • free -k | grep Mem | awk "{print($2 $4 $6)}" 
      • free 명령어 수행 후 total, free, buff+cache 값을 출력하라

sed

  • grep 명령어와 같이 한 라인씩 표준 입력으로 읽고 치환 및 삭제를 하여 표준출력 해주는 명령어

 명령어

설명 

 a\

 현재 행에 하나 이상의 새로운 행 추가

 c\

 현재 행에 새로운 내용으로 교체 

 d

 행을 삭제 

 p

 행을 출력

 n

 다음 입력행을 첫번째 명령어가 아닌 다음 명령어에서 처리 

 q

 sed 종료

 r

 파일로부터 행을 읽어온다

 s

 문자열을 치환

sed 사용예

  • sed 's/old/new/' list.txt : list.txt파일의 old를 new로 치환하여 표준출력만 수행
  • sed 's/\t/\ /' list.txt : 탭 문자를 엔터로 치환
  • sed '/TD/d' list.txt : TD문자가 포함된 줄을 삭제하고 출력
  • sed '/Src/!d' list.txt : Src문자가 있는 줄만 지우지 않고 출력
  • sed '1,2d' list.txt : 1,2줄만 지우고 출력
  • sed '/^$/d' list.txt : 공백라인을 삭제
  • sed '1,3p' list.txt : 처음부터 3번째행까지 한번더 출력
  • sed '3,$d' list.txt : 3번째라인부터 마지막까지 삭제하고 출력

xargs

  • 명령어의 출력을 다른 명령어의 인자값으로 전달하는 명령어
  • 사용예
    • find . -name "*.log" -print | xargs rm -rf 
      • 현재 디렉토리부터 하위디렉토리까지 검색되어 나오는  .log로 끝나는 파일 모두를 rm -rf 명령어로 지워라.
    • find . -name "*.java" print | xargs cat | grep System.out.println
      • 모든 .java로 끝나는 파일을 cat으로 읽고 System.out.println 구문만 출력하라


'QA > Perfomance' 카테고리의 다른 글

성능 테스트시 서버 모니터링 방법 정리  (1) 2018.01.25

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


판교에서 출퇴생활 벗어난지 1년이 넘었는데..

회의 때문에 다시 판교로 가야 된다 ㅠ.ㅠ


종로 방향으로 빠르게 퇴근하기 위해서는 9007번 버스 / 혹은 지하철을 이용해야 하는데, 

9003번 버스도 있다. 

매번 까먹어서 여기에다가 적어놓고 생각날 때마다 봐야겠다.


9003번 퇴근버스 (무정차 직행)

SK플래닛 건물 앞에서 승차!

  • 18:15분
  • 18:45분
  • 19:05분
  • 19:35분 (최근 없어짐)

사람이 많이 타기 때문에, 빠르게 승차해야 앉아갈 수 있다 ㅠ.ㅠ


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");


apache + tomcat 연동방법

  • tomcat connector 설치
  • /etc/httpd/moduels/mod_jk.so 파일 생성 확인
  • vi /etc/httpd/conf/httpd.conf
    • LoadModule jk_module modules/mod_jk.so
    • Include conf/mod_jk.conf
  • vi /etc/httpd/conf/mod_jk.conf

    <IfModule mod_jk.c>
            JkWorkersFile "/etc/httpd/conf/workers.properties"
            JkLogFile "/etc/httpd/logs/mod_jk.log"
            JkLogLevel info
            JkAutoAlias "/home/paralles/Dev/tomcat/webapps"
            JkMount /*.jsp worker1
            JkUnMount /*.html worker1
            JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
    </IfModule>
    
  • vi /etc/httpd/conf/workers.properties

    worker.list = worker1
    worker.worker1.type=ajp13
    worker.worker1.host=localhost
    worker.worker1.port=8009


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 체크박스 체크.


Open API란?

  • 다양한 서비스와 컨텐츠 그리고 데이터를 좀 더 쉽게 이용할 수 있도록 공개한 인터페이스 (application pragramming interface)
  • 내부를 몰라도 Open API를 통해 해당 서비스의 기능 및 데이터를 쉽게 이용할 수 있다. 

Rest ?

  • 기존의 soap, wsdl 기반의 웹서비스를 대체하는 방식
  • CURD를 위해 Http method 를 사용
  • stateless 임 -> 세션, 쿠키값 등을 유지하지 않음
  • 디렉토리 구조와 같은 URI를 통해 리소스 접근하고, XML/Json 데이터 구조를 통해 데이터를 전송함
  • 구성
    • HTTP URI (Resource) + HTTP Method + Message (json)
  • Method
    • GET (Read) / POST (Create) / PUT (Update) / DELETE (Delete)
  • HTTP 응답코드
    • 2xx - 성공
      • 200 OK
    • 3xx - Redirection 
      • 304 Not Modified
    • 4xx - Client Error
      • 400 Bad Request
      • 401 Unauthorized
      • 403 Forbidden
      • 404 Not Found
    • 5xx - Server Error
      • 500 Internal Server Error
      • 503 Service Unavailable
      • 504 Gateway Timeout

테스트 접근 방법

  • open api의 사용자 관점에서 접근하되, sql query라고 생각하고 접근한다.
  • api 스펙 등 문서 기반으로 접근한다.
  • 전략
    • method type별 테스트 
      • GET : 조회 결과가 있을때, 없을때 
      • POST : 중복 생성이 불가한 경우를 고려한 중복 등록 시도
      • PUT : 존재하지 않는 데이터에 대한 수정 시도, 중복이 불가한 PK값으로 수정 시도
      • DELETE : 존재하지 않는 데이터 삭제 시도 등.
    • 응답코드 확인 테스트
      • 문서에 존재하는 응답코드 별로, 응답코드를 발생시키는 테스트 수행
      • 예) 필수 파라미터 누락, 존재하지 않는 데이터 조회 등
    • 파라미터에 대한 입력 예외 케이스 
      • String type의 경우 : 빈문자, 공백문자, 앞뒤 공백문자, 특수문자, 긴 문자열 등
      • 숫자의 경우 : 문자, int 범위를 넘어서는 숫자, 음수, 0 등
      • 날짜/시간 등 : 시간 연도 구분을 넘어가는 숫자 등 (25시간, 13월 등)
      • 정의된 코드 값 : 정의되지 않은 값, 대소문자 구분 등
      • 범위형 변수 : 시작과 끝, 시작과 끝을 벗어난 값 등
    • 비즈니스 흐름기반, 혹은 사용자 시나리오 기반 테스트 수행
      • api 하나로 기능을 확인할 수 없어, 여러 api를 호출해야 기능 하나를 확인할 수 있는 경우
      • 사용자 권한에 따라 다르게 동작해야 하는 경우
      • 여러 조건에 따라 다르게 동작해야 하는 경우 등.
    • 보안 테스트 수행
      • Parameter fuzzing
      • SQL Injections
      • Username harvesting
      • Cross-site scripting
      • External entities
      • Schema invalid XML
      • Large XML document
      • Malformed XML


성능테스트 진행시 서버 자원 상태에 대해 모니터링이 필요한데, 

이에 대한 기본적인 내용을 정리해봤다. 

참고 : (도서) 실무로 배우는 시스템 성능 최적화 : 시스템 동작 분석부터 성능 개선까지 (권문수)


기본 방향

CPU
  • CPU 자원은 부족한가?
  • 실행큐에 얼마나 쌓였는가?
  • CPU 사용 유형 중 System이나 IO wait의 사용률이 높은가?
  • 프로세스별 CPU 사용률 분포는 균등한가?
메모리
  • 메모리가 부족한가? (swap이 발생하고 있는가?)
  • 서버 전체 또는 개별 프로세스 단위로 메모리 사용량이 지속적으로 증가하는가?
  • 파일 캐시 영역으로 사용하는 메모리량은 얼마인가?
디스크
  • 디스크의 서비스 시간은 디스크 대기시간을 포함해서 얼마인가?
  • 특정 디스크로 입출력이 집중됐는가?
  • 파일시스템 중 공간이 부족한 곳은 있는가?
  • 디스크 스프라이트가 잘 구성돼 있는가?
  • 스토리지 채널 병목이 있는가?
네트워크
  • 네트워크 데이터 전송량은 얼마인가?
  • 네트워크 재전송량이 많은가
  • RTT (Round-Trip time) 시간이 높은가?
  • 일반적으로 CPU > 메모리 > 디스크 > 네트워크 순으로 부족 여부를 확인한다.
  • 자원 모니터링은 5초나 10초 간격으로 한다.
  • 자원 사용률 분석은 그래프를 통해 분석하는 것이 효과적이다.
  • 자원 사용률은 프로세스와 연관시켜 분석하는 것이 좋다.

주요 모니터링 도구

netstat

  • 네트워크 connection 상태, 라우팅테이블, 인터페이스 통계 정보 등을 출력
  • 사용 예
    • netstat -anp : 열려있는 모든 포트 출력
    • netstat -anp | grep LISTEN : listen 되는 모든 포트 출력
  • 옵션
    • -a : 모든 listening, nonlistening 상태 소켓들을 출력
    • -n : ip 주소 형태로 표시
    • -p : 소켓 소유하고 있는 pid와 프로그램 이름을 출력
    • -t : TCP 소켓 리스트 출력
    • -u : UDP 소켓 리스트 출력
    • -c : 1 초 단위로 연속해서 출력
    • -r : 라우팅 테이블 정보 출력

vmstat

  • 프로세스/메모리/입출력/시스템/CPU 활동상황에 대한 정보 확인
  • vmstat <delay> <count>
  • vmstat 모니터링
    • 프로세스 관련 항목

      • r : CPU 접근 대기 중인 실행 가능 프로세스의 수
      • b : 인터럽트 불가능한 sleep 상태에 있는 프로세스의 수
    • memory 관련 항목
      • swpd : 사용된 가상 메모리 용량
      • free : 여유 메모리 용량
      • buff : 버퍼에 사용된 메모리 용량
      • cache : 페이지 캐시에 사용된 메모리 용량
    • swap 관련 항목
      • si ( swap in ) : 디스크에서 스왑된 메모리 용량
      • so ( swap out ) : 물리적 메모리가 부족할 경우 디스크로부터 사용되는 메모리 양. swap out이 지속된다면 메모리 부족을 의심할 수 있음.
    • io 관련 항목
      • bi : block device에서 받은 블록 수 (blocks/s)
      • bo : block device에서 보낸 블록 수
    • system 관련 항목
      • in : 초당 발생한 interrupts 수
      • cs : 초당 발생한 context switches 수
    • cpu 관련 항목
      • us : cpu 가 사용자 수준 코드를 실행한 시간
      • sy : cpu 가 시스템 수준 코드를 실행한 시간 
      • id : cpu가 아무런 작업을 수행하지 않은 시간
      • wa : 입출력 대기
      • st : 가상화를 사용할 경우 가상머신 cpu의 계산으로 대기된 시간
  • vmstat 옵션
    • -a : buff와 cache대신 active/inactive로 출력
    • -n : 주기적으로 헤더를 출력하지 않도록 지정
    • -S : 출력되는 데이터 단위 지정 (k, K, m, M 지정 가능 = 1000, 1024, 1000000, 1048576으로 나눈값 출력)

top

  • linux kernel을 통해 관리되는 프로세스의 태스크 리스크들의 정보 (메모리, cpu, 상태정보) 등을 확인할 수 있는 명령어
  • 사용법
    • top
    • top -d 1
  • 옵션
    • -d : delay
    • -n : interactions
    • -p : pid

sar

  • top와 마찬가지로 cpu/memory/hdd 사용량 통계치 등을 모니터링할 수 있지만, sar는 history 및 최종 통계치를 볼 수 있다.
  • sar 명령을 사용하려면 sysstat package가 설치 되어 있어야 한다.
    • yum install sysstat
  • sar <option> <interval> <count>
  • 옵션
    • -u : cpu activity
    • -r : memory activity
    • -d : disk i/o activity
    • -A : report overall system performance

free

  • 현재 시점의 메모리 상태를 쉽게 확인할 수 있음.
  • free <-b|-k|-m|-g><option>
  • 옵션
    • b/k/m/g : 메모리양을 바이트/킬로바이트(기본값)/메가바이트/기가바이트로 표시한다.
    • -t : 총계가 포함된 줄을 출력
    • -o : 버퍼에 조정된 줄의 출력을 비활성화 한다.
    • -s : delay 초마다 계속해서 출력하도록 한다.

ps

  • 현재 수행되고 있는 프로세스 확인하는 명령어
  • ps -ef | grep httpd (특정 프로세스 확인)
  • ps -ef | wc -l (현재 기동중인 프로세스 총 수 확인)

CPU Monitoring

  • 안정적인 운영을 위한 CPU 사용율 기준
    • CPU 사용률 : CPU 70% 이하
    • CPU 실행큐 : CPU core 당 평균 3개 이하
  • 전체 CPU 기준으로 성능 평가를 할 때는 이중화 구성 등에 따른 부분 장애시에 대한 변화량/사용량을 맞춰서 판단할 필요가 있다. 
  • CPU 사용량 상세 분석
    • System : 커널모드 시스템 콜 호출에 사용된 CPU 사용량.
      • 시스템 콜이라 함은 프로세스 제어, 장치 관리, 파일과 네트워크 관리, 입출력 처리, 시스템 정보와 시간 관리 등에 관련된 함수
      • 일반적으로 전체 사용량 대비 30% 미만인데, system cpu가 높게 나타난다면 어떤 유형의 시스템 콜인지 분석할 필요가 있다 
      • 시스템 콜 모니터링 도구  : truss / pstack / jstack
    • User : 일반 함수를 실행하는데 사용된 CPU 사용량. WAS나 DB 서버 경우 User CPU를 사용한다.
    • IO Wait : 프로세스나 스레드가 CPU를 할당받아 사용할 수 있는 상태가 됐으나, 입출력이 완료되기를 기다리고 있어 CPU를 사용할 수 없는 상태의 사용량
      • 일반적으로 전체 사용량 대비 20% 미만인데, 높게 나타난다면 입출력이 과다하게 발생하는 것은 아닌지 디스크 사용률 등을 확인하면 된다.
      • io wait 모니터링 도구 : netstat / iostat / sar
    • Idle : 사용하지 않는 CPU 여유율
  • 기타 모니터링 방법
    • CPU core 수 확인 방법 (리눅스 기준) : cat /proc/cpuinfo
    • 커널 처리 비트 확인 방법 (리눅스 기준) : getconf WORD_BIT
    • CPU를 많이 사용하는 스레드 식별하는 방법 : top -H , ps -eLf | grep pid
    • 프로세스의 누적 CPU 사용량 확인하는 방법 : ps -ef

Memory Monitoring

  • 메모리 사용패턴이 100% 라고 해도 부족하지 않으면 성능저하가 발생하지 않는다. 
    • 운영체제 측면에서는 페이징스페이스에 대한 스왑 발생 여부로 판단.
    • 자바기반 솔루션 (was 등) 등은 설정한 힙메모리 이상을 사용하지 않기 때문에 운영체제 메모리 부족이 발생할 가능성은 적다.
  • 메모리 관련 용어
    • pagingspace : 메인메모리가 부족할 때 사용하는 디스크 공간, swap space라고도 부름.
      • 운영체제가 메인 메모리 크기 이상의 메모리를 사용할 수 있도록 해주는 역할.
      • 성능 관점에서보면 디스크에 프로세스 메모리를 쓰고 읽는 스와핑 작업으로 인해 큰 성능 저하가 발생한다.
      • pagingspace 크기 확인 방법 : cat /proc/swaps
    • paging : 
    • swapping : 메모리에서 페이지 혹은 세그먼트 단위 데이터를 교환하는 것. 컴퓨터가 메모리보다 큰 프로그램을 실행하거나 메모리보다 큰 데이터 파일을 다룰 수 있게 함.
    • page fault : 페이징 방식의 가상 메모리에서 CPU가 사용하려는 페이지가 메인 메모리에 없는 경우. 
    • page in : 가상 메모리에서 page fault가 발생했을때 디스크에 있는 프로그램이나 데이터를 메모리로 로드하는 것.
    • page out : 가상 메모리에서 page fault가 발생했을 때 메모리가 부족하면 기존 메모리를 디스크로 기록하는 것.
    • page scan rate : 운영체제는 일정량의 여유 페이지를 확보해서 필요한 경우 즉시 제공하기 위해 page scan이라는 검색을 통해 해제함으로써 여분으로 확보할 페이지를 찾는다. 
  • 안정적인 운영을 위한 메모리 판단 기준
    • 메모리 사용률 : 100% 이하
    • 지속적으로 프로세스 스와핑이 발생하지 않는지 확인
  • 일반적인 메모리 사용률 산출
    • 전체 메모리 total : used + free + buffers + cached
    • 실제 free 메모리 : free + buffers + cached
    • 실제 메모리 사용량 : total - (free+buffers+cached)
  • 메모리 총량 확인 방법 : cat /proc/meminfo
  • 프로세스 메모리 사용량 확인 방법 : ps -euf
  • 파일 캐시 확인 명령 : /proc/sys/vm/buffermem, free -m, vmstat -v

Disk I/O 

  • 시스템상 디스크 영향도 확인
    • 자원 영향도 : CPU 사용률에서 io wait 가 비정상적으로 높은지?
    • 디스크 영향도 : 디스크 대기시간과 서비스 시간이 높은지?
    • 어플리케이션 영향도
      • pstack/jstack 으로 스택을 반복 수집했을 때 서비스 중인 스레드 가운데 파일 입출력 관련 작업 중인 스레드의 비중이 높은지
      • lsof/pfiles로 확인한 로그 파일이나 데이터 파일의 크기가 큰지?
      • truss/tusc로 모니터링 했을 때 발생하는 입출력의 양이 많은지?
  • 디스크 입출력 모니터링 방법
    • sar -d <second> <count>
    • iostat <option> <second> <count>
  • 파일시스템 여유율 확인 방법
    • df -k

APM Solution

참고)

Java Heap Memory 

  • JVM 메모리 구조 및 GarbageCollator
    • 메소드 영역

      • 자바 프로그램을 구성하고 있는 메소드와 클래스 변수(static으로 선언된 변수) 저장하기 위한 공간이다.

      • JVM 복수개의 스레드가 메소드를 정상적으로 사용하기 위한 동기화 기법을 제공

    • 힙 영역

      • 프로그램 상에서 데이터를 저장하기 위해 동적으로(실행시간에)할당하여   있는 메모리 영역

      •  new 연산자를 통하여 개체를 동적으로 생성시

      • 메소드 영역과 같이 모든 프로그램에 의해 공유되는 공간 -> 동기화 기법 이용

      • GC(GarbageCollection)으로 관 되는 영역

        • Permanent Space : Class 대한 Meta 정보를 저장하는 공간

        • New Generation

          • Eden : new 생성된 모든 객체

          • Survivor1(From) : Minor GC 의해서 Eden, Survivor 2영역의 객체  활성화  객체만 이동하여 위치, Old Space 이동되기 전의 객체만 위치

          • Survivor2(To) : Minor GC 의해서 Eden, Survivor 1영역의 객체  활성화된 객체만 이동하여 위치, Old Space 이동되기 전의 객체만 위치

          • Old Generation : Survivor 1, Survivor 2 영역에서 이동해온 객체만 위치, Full GC 대상이 되는 객체가 위치

    • 스택영역(Stack area)
      • 메소드가 호출되어 실행될  멤소드의 매개변수메소드 내에 선언된 메소드 지역변수반호나  변수 등을 저장하기 위한 공간
      • 메소드 호출시 필요로 되는 변수들을 스택에 저장하고메소드 실행이 끝나면 스택을 반환하게 된다.
    • 네이티브 메소드 스택
      • 프로그램이 natie 메소드를 호출시 native 메소드의 매개변수, 지역변수 등을 저장하기 위해 사용하는 공간 native 메소드는 자바 언어가 아닌 기존의 다른 언어에서 제공되는 메소드를 의미

  • java heap memory 누수
    • 원인
      • 사용자 세션이나 캐시 데이터의 증가로 인한 메모리 증가
      • 로직 오류로 참조 레퍼런스가 끊어져야 되는데 그렇지 못해 GC대상에서 누락
      • 대용량 조회나 처리 등에서 발생
    • 확인 방법
      • Full GC 이후 old 영역 메모리 사용량이 지속적으로 증가하는지 여부로 판단.
  • java heap memory  monitoring
    • jstat
    • jconsol
    • gc logging
  • gc logging 옵션
    • -Xloggc:<path to file><filename>
    • -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
    • -verbose:gc 
  • java heap dump 
    • jmap -dump:format=b,file=12345_dump.hprof 12345 (pid가 12345일때)
    • kill -3 or Ctrl + Break 
    • java -Xrunhprof:heap=all,cpu=samples,thread=y,cutoff=0,format=a,doe=n,com.TestRun
    • jvm option
      • -XX:+HeapDumpOnOutOfMemoryError
      • -XX:+HeapDumpPath=/logs/app/dump 
      • -XX:+HeapDumpOnCtrlBreak

 

'QA > Perfomance' 카테고리의 다른 글

성능 테스트시 주로 사용하는 Shell 명령어 사용법  (0) 2018.03.05

appium으로 사내 서비스 자동화를 진행하다가, junit report나 surefire report 포맷이 별로라서, 좀 더 새로운 html report를 찾다가 발견한 extent report.


좀 더 이쁘장하고, 결과에 따라 필터링도 된다. 

다만, junit 결과를 자동으로 report로 변환하는게 아니라서, 테스트 이후 결과에 따른 로그를 직접 넣어야 된다. 


selenium이나 appium 자동화에 사용하는 사례도 구글링하면 좀 나오는거 보니, 쓸만한 것 같아 적용하기로 했고, 

실제 ui 자동화랑 api 자동화 업무에 해당 리포트를 사용하고 있다. 


우선, maven 설정을 추가하고,

<dependency>
    <groupId>com.aventstack</groupId>
    <artifactId>extentreports</artifactId>
    <version>3.1.2</version>
</dependency>


  • 테스트 시작 시점에는 createReport
  • 테스트케이스 시작시점에는 createTest 
  • 테스트 종료시점에 pass/fail/skip 의 결과를 extent report에 작성-> test.log(STATUS.PASS...)


우선 report 생성할때, 설정 내용을 반영하도록 해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static ExtentReports createReport() throws Exception {
    if(extent != nullreturn extent;
 
    String reportFile= new File("target/result.html").getAbsolutePath();
 
    htmlReporter = new ExtentHtmlReporter(reportFile);
    htmlReporter.setAppendExisting(true);
    htmlReporter.config().setChartVisibilityOnOpen(true);
    htmlReporter.config().setDocumentTitle("타이틀적용");
    htmlReporter.config().setEncoding("UTF-8");
    htmlReporter.config().setReportName("리포트제목");
 
    extent = new ExtentReports();
    extent.setSystemInfo("OS""Windows 7");
    extent.attachReporter(htmlReporter);
 
    return extent;
}
cs


테스트 시작시

1
2
3
4
5
@BeforeClass
public static void setUp() throws Exception {
    enableLoggingOfRequestAndResponseIfValidationFails();
    extent = createReport();
}
cs


케이스 실행 시작 시점

1
2
3
4
@Before
public void beforeMethod() throws Exception {
    test = extent.createTest(methodName);
}
cs

케이스 종료 시점

1
2
3
4
@After
public void afterMethod() throws Exception {
    extent.flush();
}
cs

테스트 결과에 따라 리포트 로그를 남겨야 하기에 TestWatcher를 활용.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Rule
public TestWatcher testWatcher = new TestWatcher() {
 
    @Override
    protected void failed(Throwable e, Description description) {
        test.log(Status.FAIL, e.toString());
    }
 
    @Override
    protected void succeeded(Description description) {
        test.log(Status.PASS, "SUCCESS");
    }
 
     @Override
    protected void skipped(AssumptionViolatedException e, Description description) {
        test.log(Status.SKIP, SKIP_MSG);
    }
 
}
cs


대충 이정도 구성해놓으면, 각 테스트케이스 @Test 단위에서는 기존과 같이 자동화 코드를 작성하면 된다.


덧붙여 좀 더 추가해서 신경쓸 부분이 있다면, 

  • test.assignCategory(SuiteName); 등을 추가해서, 카테고리별로 구분해서 보게 할 수 있다.
  • 혹시 retry 를 사용하고 있다면, retry시에는 createTest를 추가할 필요가 없다.
  • report에 screenshot을 추가하고 싶다면, test.log(...).addScreenCaptureFromPath() 를 사용하면 된다.
  • jenkins에 연동할때에는 CSS가 적용될 수 있도록 jenkins에 CSS 관련 설정을 해야 한다.


더 좋거나 쉬운 리포트 라이브러리가 있으면 찾아보겠지만, extent report만으로도 현재까지는 만족.





'QA > Test Automation' 카테고리의 다른 글

SoapUI를 이용한 API 테스트 방법 정리  (0) 2018.01.28
API 테스트 방법  (0) 2018.01.27
Jenkins와 Sonar 연동하기  (0) 2012.07.19
Ant 로 Sonar 수행하기.  (0) 2011.04.12
Sonar 소개  (0) 2011.02.14

하도 오래전에 Jenkins와 Sonar를 연동해봤었는데,

요번에 BMS 프로젝트 진행하면서 Sonar한번 설치할래니 기억이 가물가물..;;


그래서 다시 이곳에 정리하기로 했다. 우선 Jenkins와 Sonar가 설치되어 있다는 가정하에 내용을 정리하겠다.


  1. Jenkins에 Sonar Plugin을 설치해야 한다. 
    • Jenkins 관리 > 플러그인 관리
  2. Maven 관련 설정을 한다. Sonar 자체가 Maven기반으로 동작하기 때문에 Maven설정은 필수다.
    • Jenkins 관리 > Configuration (시스템 설정) > Maven
  3. Sonar 관련 설정을 한다.
    • Jenkins 관리 > Configuration (시스템 설정) > Sonar
  4. Build Job을 생성하고 Build 관련 설정을 한다. 
    1. Build Job > 설정 > Build 관련 설정
      • root pom.xml 을 설정하고, goal에서는 -DskipTests=true를 꼭 넣어준다. sonar에서 test를 수행하기 때문에 저 옵션을 넣지 않으면 test가 두번 수행된다.
    2. Build Job > 설정 > Post-build Actions > Sonar 관련 설정
      • Add post-build action에서 Sonar를 선택하고, Sonar관련 설정을 한다.
      • -Dsonar.projectVersion옵션을 사용하면 Sonar에 version 정보를 전달할수 있다. 옵션을 사용하지 않으면 pom.xml의 <version> 정보가 sonar로 넘어간다. 
  5. Jenkins에서 Build를 수행한다. 연동 완료!


'QA > Test Automation' 카테고리의 다른 글

API 테스트 방법  (0) 2018.01.27
자동화에 extent report 적용하기  (0) 2018.01.22
Ant 로 Sonar 수행하기.  (0) 2011.04.12
Sonar 소개  (0) 2011.02.14
CI(Continuous Integration) 서버 구성안  (0) 2011.02.14

JIRA와 TestLink를 연동하는 방법을 아래에 기술한다.

JIRA 설정
1. Administration > Global Settings 하위의 General Configuration > Options 에서 Accept remote API calls 를 ON으로 설정한다.
2. JIRA RPC Plugin 을 설치한다.

TestLink 설정
1. config.inc.php 와 Custom_config.inc.php 파일에 $g_interface_bugs = 'JIRASOAP'; 로 설정
2. jirasoap.cfg.php 파일을 아래와 같이 수정
/** The Username being used by JIRA logon */
define('BUG_TRACK_USERNAME', 'jirauser');
 
/** The Password being used by JIRA logon*/
define('BUG_TRACK_PASSWORD', 'jirapassword');
 
/** link of the web server for JIRA*/
define('BUG_TRACK_HREF',"http://192.168.1.22:8080/");
 
* The values here are relative to the BUG_TRACK_HREF property *
 
/** path of JIRA WSDL */
define('BUG_TRACK_SOAP_HREF', "rpc/soap/jirasoapservice-v2?wsdl");
/** link of the web server for jira ticket*/
define('BUG_TRACK_SHOW_BUG_HREF', "browse/");
/** link of the web server for creating new jira ticket*/
define('BUG_TRACK_ENTER_BUG_HREF',"secure/CreateIssue.jspa");


  1. Acid 3 Test http://acid3.acidtests.org/
  2. W3C HTML4 Test Suite http://www.w3.org/MarkUp/Test/HTML401/current/
  3. W3C HTML5 Test Suite http://w3c-test.org/html/tests/harness/harness.htm
  4. HTML 5 Test http://html5test.com
  5. DOM Conformance Test Suite http://www.w3.org/DOM/Test/
  6. W3C XML Test Suite http://www.w3.org/DOM/Test
  7. JIL 1.2.2 Tests
  8. Sputnik Sputnik Sputnik ? JavaScript Conformance http://sputnik.googlelabs.com/
  9. JavaScript tests & Compatibility tables http://robertnyman.com/javascript/
  10. Native JSON TestNative http://robertnyman.com/javascript/javascript-native-json.html
  11. ECMAScript 3 Conformance Test Suite http://kangax.github.com/sputniktests-webrunner/
  12. CSS 2.1 Conformance Test Suite http://test.csswg.org/suites/css2.1/20110323/
  13. CSSCSS 3 Color Conformance Test Suite http://www.w3.org/Style/CSS/Test/CSS3/Color/current/
  14. Quirksmode background Test http://www.quirksmode.org/css/background.html
  15. W3C CSS3 Media Queries Test http://www.w3.org/Style/CSS/Test/MediaQueries/20100726/
  16. W3C CSS3 Selectors Test http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/
  17. CSS3 Selectors Test http://www.css3.info/selectors-test
  18. W3C XHR Test Suite http://tc.labs.opera.com/apis/XMLHttpRequest/
  19. W3C SVG Test Suite http://www.w3.org/Graphics/SVG/WG/wiki/Test_Suite_Overview
  20. DOM Level 1http://dorothybrowser.com/test/android/conformance/dom/level1/core/alltests.html?implementation%3Diframe%26skipincompatibletests%3Dtrue%26contenttype%3Dtext/html
  21. DOM Level 2 Corehttp://dorothybrowser.com/test/android/conformance/dom/level2/core/alltests.html?implementation=iframe&skipIncompatibleTests=true&autoRun=true&contentType=text/html
  22. DOM Level 2 HTMLhttp://dorothybrowser.com/test/android/conformance/dom/level2/html/alltests.html?implementation=iframe&skipIncompatibleTests=true&autoRun=true&contentType=text/html
  23. W3C XHR Test Suite http://tc.labs.opera.com/apis/XMLHttpRequest/testrunner.htm
  24. SVG 1.1 Tiny Test Suitehttp://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/tiny-index.html

참고할 만한 링크자료

고급 Bash Scripting Guide : http://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html
Shell Programming 강좌 : http://wiki.kldp.org/KoreanDoc/Shell_Programming-KLDP


http://www.tpc.org/tpce/
물론 위 링크에서 EGen을 다운 받아서 수행하면 될 것 같지만, 여러가지 문제점이 많이 발생하는 관계로, Lauchpad Percona-tools project에서 tpcemysql 을 다운 받는다.

이는 물론 TPC-E like한 것 뿐이라서 동일하지는 않지만, 같은 database구조로 같은 query를 날리는 것 같다.

우선 linux에서 bzr 이 설치 되어 있는지 확인하고, 안되어 있으면 설치한다.
# yum install bzr

이 후 bzr 을 이용해 Lauchpad Percona-tools project에서 tpcemysql을 다운 받는다.
# bzr branch lp:~percona-dev/perconatools/tpcemysql

mysqltpce를 수행하기에 앞서서 unixODBC, unixODBC-devel package와 make를 위해 gcc-c++ package가 설치되어 있어야 하므로, 기설치여부를 확인하고 설치한다.
# yum install unixODBC, unixODBC-devel, gcc-c++

다운받은 tpcemysql의 prj 디렉토리로 이동하면 Makefile이 존재한다. 그 곳에서 make를 수행한다.
# cd tpcemysql/prj
# make

make를 수행하기 전에 혹시 64bit 머신이라면 Makefile의 옵션을 수정해본다.(아직 이 옵션에 대한 의미가 확실치 않음)
  # Defines for Linux (MySQL C API Wrapper)
  CXX=g++
! CCFLAGS=-g -O2 -Wall -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -I/usr/include/mysql -DMYSQL_ODBC -DODBC_WRAPPER -DUSE_PREPARE
  LDFLAGS=-g -O2 -Wall
  LIBS=-lpthread -lmysqlclient_r
--- 23,29 ----
  # Defines for Linux (MySQL C API Wrapper)
  CXX=g++
! CCFLAGS=-g -O2 -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -I/usr/include/mysql -DMYSQL_ODBC -DODBC_WRAPPER -DUSE_PREPARE
  LDFLAGS=-g -O2 -Wall
  LIBS=-lpthread -lmysqlclient_r

make가 성공적으로  완료되면 tpcemysql의 bin디렉토리에 3개의 파일이 생성되어 있을 것이다.
* EGenLoader, EGenSimpleTest, EGenValidate

tpcemysql 홈디렉토리에서 아래와 같이 수행한다. (꼭 홈디렉토리에서.. 아니라면 flat_in, flat_out옵션을 따로 주어야 함)
# ./bin/EGenLoader -c 1000 -t 1000 -w 3

사실 이정도로 옵션을 주고 데이터를 생성하는 것은 TPC-E specification 에 비해서 너무 작다. 하지만, EGenLoader의 default값으로 수행하면 하루 죙일.. 걸리는 것 같다. 동작을 확인하기 위해서 우선 작은 값으로 수행하는 것을 알아두자.

그 다음, tpcemysql/script/mysql 디렉토리로 이동하여 해당 query들을 수행하자. 수행하기전, database와 user를 생성해 두는 것은 잊지 말자.
# mysql -u root -p
# create database tpce;
# grant all privileges on tpce.* to 'tpce'@'localhost' identified by 'tpce';
# flush privileges;

# cd tpcemysql/script/mysql
# mysql -u tpce -p tpce < 1_creat_table.sql
# mysql -u tpce -p tpce < 2_load_data.sql
# mysql -u tpce -p tpce < 3_create_fk.sql
# mysql -u tpce -p tpce < 4_create_index.sql
# mysql -u tpce -p tpce < 5_create_sequence.sql

query까지 수행하였다면, 이젠 EGenSimpleTest를 이용해서 테스트 하기만 하면 된다.
# ./bin/EGenSimpleTest -S localhost -D tpce -d 30 -t 180 -r 60 -u 8


참고 URL :
http://d.hatena.ne.jp/sh2/20100510
http://www.tpc.org/tpce/
http://www.mysqlperformanceblog.com/?s=tpc+e

'System > MySQL' 카테고리의 다른 글

mysql 기본 명령어 정리  (0) 2011.03.30
빌드는 maven으로 하고, sonar 구동 및 전체 수행은 ant 로 수행시키는 build.xml 예제.

사내 build에 적용해야 하는데, 아직 미 완성.
좀 더 프로세스를 구체화 시킨 후 적용할 예정이다.

<?xml version="1.0" encoding="UTF-8"?>
<project name="Sonar Ant Project" default="build" basedir="." xmlns:artifact="antlib:org.apache.maven.artifact.ant">
 <property environment="env"/>
 <path id="maven-ant-tasks.classpath" path="${basedir}/lib/maven-ant-tasks-2.1.1.jar"/>
 <typedef resource="org/apache/maven/artifact/ant/antlib.xml"
             uri="antlib:org.apache.maven.artifact.ant"
             classpathref="maven-ant-tasks.classpath" />
 <taskdef resource="net/sf/antcontrib/antlib.xml">
   <classpath>
     <pathelement location="${basedir}/lib/ant-contrib-1.0b3.jar" />
   </classpath>
 </taskdef>
 <taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
    <classpath path="lib/sonar-ant-task-1.0.jar" />
 </taskdef>
 <target name="build" depends="mvn,sonar"/>
 <target name="mvn">
   <property name="maven.home" value="${env.M2_HOME}"/>
   <echo message="M2_HOME = ${maven.home}"/>
   <artifact:mvn pom="pom.xml" mavenHome="${maven.home}" fork="true" failonerror="true">
     <arg value="clean"/>
     <arg value="install"/>
     <arg value="-Dmaven.test.skip=true"/>
    </artifact:mvn>
 </target>
 <target name="sonar">
   <tstamp>
     <format property="build.time" pattern="yyyy-MM-dd.hh:mm" locale="en"/>
   </tstamp>
  <!--
  <property file="build.number" />
  <echo message="build.number = ${build.number}"/>
  <buildnumber file="build.number" />
  -->
  <!-- The workDir directory is used by Sonar to store temporary files -->
  <sonar:sonar workDir="." key="org.example:example" version="${build.time}" xmlns:sonar="antlib:org.sonar.ant">
    <sources>
      <path location="${basedir}/common/src/main/java"/>
      <path location="${basedir}/model/src/main/java"/>
      <path location="${basedir}/dao-api/src/main/java"/>
      <path location="${basedir}/dao-hibernate/src/main/java"/>
      <path location="${basedir}/agent/src/main/java"/>
      <path location="${basedir}/manager/src/main/java"/>
    </sources>
    <tests>
      <path location="${basedir}/common/src/test/java"/>
      <path location="${basedir}/model/src/test/java"/>
      <path location="${basedir}/dao-api/src/test/java"/>
      <path location="${basedir}/dao-hibernate/src/test/java"/>
      <path location="${basedir}/agent/src/test/java"/>
      <path location="${basedir}/manager/src/test/java"/>
    </tests>
   <!--
    1. binaries: binaries directories, which contain for example the compiled Java bytecode (optional)
    2. libraries: path to libraries (optional). These libraries are for example used by the Java Findbugs plugin
    <binaries>
      <path location="..." />
    </binaries>
    <libraries>
      <path location="..." />
    </libraries>
   -->
   <!-- list of properties (optional) -->
   <property key="sonar.projectName" value="Sonar Ant Project" />
   <property key="sonar.dynamicAnalysis" value="true" />
   <property key="sonar.jdbc.url" value="jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8" />
   <property key="sonar.jdbc.driverClassName" value="com.mysql.jdbc.Driver" />
   <property key="sonar.jdbc.username" value="sonar" />
   <property key="sonar.jdbc.password" value="sonar" />
   <property key="sonar.host.url" value="http://192.168.20.34:9000" />
   <property key="sonar.java.source" value="1.6" />
   <property key="sonar.java.target" value="1.6" />
  </sonar:sonar>
 </target>
</project>
sonar를 ant로 구동시키면, modules(sub-projects)가 지원되지 않는 점 때문인지, tree map이 package이름으로 번잡하게 나오고, tangle index 정보가 나오지 않는다. 안타깝다;

데이터 베이스 접속시
# mysql --user=root -p 
Enter password :

# mysql -u root -p
Enter password :

MySQL 설치한 직후 root 계정에 password 변경
# mysqladmin -u root password 새비밀번호

# mysql -u root mysql
  mysql> update user set password=password('새비밀번호') where user='root';
  mysql> flush privileges;

사용자 추가
mysql> grant all privileges on dbname.* to 'username'@'localhost' identified by 'password';
mysql> flush privileges;

사용자 삭제
mysql> delete from user where user='username';
mysql> flush privileges;

데이터베이스 생성
mysql> create database dbname;

존재하는 데이터베이스 목록 보기
mysql> show databases;

특정 데이터베이스 사용하기
mysql> user dbname;

데이터베이스 삭제
mysql> drop database dbname;

테이블 생성 예제
mysql> create table tablename ( column_name1 int, column_name2 varchar(20) );

현재 데이터베이스에서 존재하는 테이블 목록 보기
mysql> show tables;

테이블 구조 보기
mysql> explain tablesname;
mysql> describe tablename;

테이블 삭제
mysql> drop table tablename;

현재상태보기
mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.10, for Win64 (x86)
Connection id:          156
Current database:
Current user:           user@localhost
SSL:                    Not in use
Using delimiter:        ;
Server version:         5.5.10 MySQL Community Server (GPL)
Protocol version:       10
Connection:             localhost via TCP/IP
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    latin1
Conn.  characterset:    latin1
TCP port:               3306
Uptime:                 2 hours 18 min 59 sec
Threads: 1  Questions: 23798  Slow queries: 6  Opens: 188  Flush tables: 1  Open  tables: 0  Queries per second avg: 2.853
--------------

사용자 추가
mysql> grant all on *.* to 'username'@'localhost' identified by 'password';
mysql> grant all on dbname.* to 'username'@'localhost' identified by 'password';
mysql> flush privileges;

mysql 원격접속 설정
mysql> grant all privileges on dbname.* to 'username'@'접속ip' identified by 'password';
mysql> flush privileges;

'System > MySQL' 카테고리의 다른 글

mysql에서 tpc-e 테스트 하기  (0) 2011.05.03

사내에서 JIRA를 관리하고 있는데, 반복되는 백업/복구 작업 때문에, 자주 Plugin설치를 하게 된다. JIRA나 Confluenc는 백업/복구시에 Plugin까지 복구해주지 않는 것 같다.

따라서, 유용한 Plugin 목록들을 정리해둔다.

유용한 Plugin 목록
  1. Universal Plugin Manager Plugin : JIRA Plugin 관리를 용이하게 해준다. JIRA 4.3 부터는 기본으로 포함되어 있다.
  2. JIRA Linker Plugin : Confluence Link Custom Field를 생성하게 해주고, Confluence Search를 JIRA에서 할 수 있다.
  3. JIRA Subversion Plugin : Subversion과 JIRA의 연동. Commit시 JIRA-Issue번호를 적어주면 된다.
  4. JIRA Gantt Chart Plugin : JIRA Issue의 진행 일정을 Gantt Chart에서 표현해준다. 조금 아쉬운 기능.
  5. Marvelution JIRA Sonar Plugin : JIRA 와 Sonar 의 연동.
  6. JIRA Drag and Drop Attachment Plugin : Attachment를 붙일때, D&D로도 가능하게 해준다.
  7. CustomWare JIRA Utilities : 몇몇의 Custom Field를 추가할 수 있게 해준다. 아직 기능을 다 파악 못했다.
  8. JIRA Calendar Plugin : JIRA Issue의 date(update, create, resolved..)를 기준으로 calendar에 표시해주는 기능을 제공한다
  9. JIRA Charting Plugin : 추가 Chart 및 Report 제공.
  10. JIRA Commit Acceptace Plugin : Commit시 제약을 걸 수 있는 듯. 아직 파악을 못함.
  11. JIRA Workflow Designer : Workflow를 그래픽하게 디자인 할 수 있도록 제공하는 기능. 한번 써봤는데, 에러났다.;;
  12. Marvelution JIRA Hudson Plugin : JIRA와 Hudson의 연동.
  13. JIRA Labels Plugin : Label Custom Field를 생성할 수 있고, 이를 통해 빠른 검색이 가능하다. JIRA 4.2 버전부터는 기본 포함되어 있다.
  14. GreenHopper(Commercial)
  15. Tempo(Commercial)

Plugin 설치 방법 (UPM으로 설치 되지 않는 Plugins)


  • JIRA Subversion Plugin
      1. 다운로드 받은 jar파일의 lib디렉토리에 있는 *.jar를 JIRA의 WEB-INF/lib 디렉토리로 copy한다.
      2. 다운로드 받은 jar파일안의 subversion-jira-plugin.properties 파일을 JIRA의 WEB-INF/classes 디렉토리로 copy한다.
      3. JIRA의 WEB-INF/classes디렉토리의 jira-application.priperties를 열어서 jira.options.ignore.url.with.key값을 false로 설정한다.
      4. Administration탭의 subversion repositories에서 svn연결을 설정한다.
    • reference : https://studio.plugins.atlassian.com/wiki/display/SVN/Subversion+JIRA+plugin

  • JIRA Linker Plugin
      1. JIRA의 WEB-INF/lib 디렉토리에 jar를 copy하거나 Universal Plugin Manager를 통해 Confluence Linker Plugin을 install한다.
      2. JIRA의 images/icons 디렉토리에 search_16.png를 copy해 둔다.
      3. JIRA의 WEB-INF/classes 디렉토리에 atlassian-jira-linker-plugin.properties 파일을 생성하여 아래와 같이 내용을 추가하고 copy해 둔다.
      4. Confluence의 General Configuration에서 Anonymous Remote API Access 설정을 Enable시켜놓는다.
      5. Confluence의 Globel Permission에서 Anonymous user access를 할 수 있게 설정해둔다.
      6. Confluence의 link를 원하는 space에 anonymous view access를 허용하도록 한다.
      7. Restart JIRA.
      8. JIRA Admin권한으로 Custom Fields > Add a new custom field > URL Link Field 선택 하여 Field추가한다.
      9. You're done!
    • reference : https://studio.plugins.atlassian.com/wiki/display/JLINK/Home

  • JIRA Commit Acceptance Plugin
    • Server Installation
      1. jira-commitacceptance-plugin-xxx.jar 를 JIRA의 WEB-INF/lib 디렉토리로 copy한다.
      2. Administration 탭의 General Configuration에서 enable JIRA remote API calls를 enable해놔야 한다.
      3. restart JIRA
    • Client Installation ( Perl, Subversion )
      1. Perl, Python 버전의 script 묶음이 있는데, 적절한 버전과 version control client를 선택하면 된다. (ex. perl, subversion)
      2. Subversion client는 pre-commit hook으로 구현되어 있다.
      3. jira-client.pl과 pre-commit.bat를 Subversion Repository Home의 hooks 디렉토리로 copy한다.
      4. pre-commit.bat 에 perl interpreter full path와 jira-client.pl의 full path를 적어준다.
      5. jira-client.pl에 jira access setting(URL, username, password, JIRA project key)내용을 적고, svnlook pull path도 적어둔다.
    • reference : https://studio.plugins.atlassian.com/wiki/display/CMMT/JIRA+Commit+Acceptance;jsessionid=FC08278D5E18EAED1DA3AA61CBA81B3B
  • Marvelution JIRA Sonar Plugin
      1. Shutdown jira server
      2. jira-sonar-plugin-xxx.jar 를 JIRA HOME의 plugin에 copy한다.
      3. start jira server
  • Marvelution JIRA Hudson Plugin

CI서버를 어떻게 구축하느냐 고민하면서 자료 검색을 하던 도중에
Sonar라는 것을 알게 되었다.

Sonar는 Codehaus에서 개발한 코드 품질 관리 플랫폼으로, 오픈소스다.

사실 이전에 작성하였던 PMD, Checkstyle, Findbugs, Cobertura, JavaNCSS 등을 Maven에 연동하다가 안되는 것이 많아서, 고민하던 차에 알게된 것이라 더욱 반가웠다.

PMD, CheckStyle, Findbugs, Cobertura등을 이용해서 코드검사, 코드커버리지, 중복도, 복잡도 등의 데이터를 추출해주고,
그 외 품질관련 데이터도 뽑아주기 때문에 수월하게 좋은 데이터를 얻을 수 있다.
 

설치도 간단하고, 사용도 쉬워서
이미 엄청나게 유명할 수도 있겠지만, 국내에서도 많이 사용할 것 같다.

테스트 후 나온 Sonar 결과 화면을 아래 첨부한다. 보시다시피, 왠지 엄청 좋아보인다. Quality Index나 Technical Debt까지 계산해주다니...훗^^

다음에는 Sonar 설치, Hudson 연동 방법, Sonar Profile 설정 방법, Sonar 결과화면의 각 데이터의 의미에 대해서 차례로 등록할 예정이다.

종 류
이 름
관련자료 링크
비 고
빌드서버
Hudson
직관적인 UI와 다양한 plugin을 제공
빌드Tool
Maven
단위테스트
프레임웍
JUnit
정적분석Tool
FindBugs
컴파일된 바이너리(.class) 파일을 분석하여 결함을 찾는 도구
PMD
 FindBugs는 클래스 파일을 분석하는 반면 PMD는 미리 정의한 룰셋을 기반으로 자바코드의 구분을 분석한다.
코드커버리지
Cobertura
 branch 커버리지와 line커버리지를 제공
코딩컨벤션 검사
CheckStyle
코드 중복 검사
CPD
  1. PMD에 포함된 코드중복 도구
  2. 자바뿐 아니라 다른 언어도 지원(C/C++, PHP, 포트란 등)
  3. 프롬프트, 자바스윙, 자바 웹스타트 환경에서 실행할 수 있음
코드 복잡도
검사도구
JavaNCSS
 

'QA > Test Automation' 카테고리의 다른 글

자동화에 extent report 적용하기  (0) 2018.01.22
Jenkins와 Sonar 연동하기  (0) 2012.07.19
Ant 로 Sonar 수행하기.  (0) 2011.04.12
Sonar 소개  (0) 2011.02.14
Continuous Integration 관련 자료 - IBM DeveloperWorks  (0) 2011.01.04

사내에서 사용하는 Confluence (3.4.2버전) 의 Calendar Plugin이 드디어 나왔다.

관련 링크 : https://plugins.atlassian.com/plugin/details/153?versionId=21689

그동안 낮은 버전밖에 지원하지 않아서,
Calendar plugin을 설치되지 않는 최신 버전의 설치까지 망설였을 정도였는데,
간만에 검색해보니 최신버전이 어느샌가 나와있었던 것이다.

Universal Plugin Manager에서 Install 버튼을 누르는 순간. 에러가 발생하였다.
log를 뒤져보니..
아래와 같은 로그가 찍혀있었다.

중략..
Caused by: net.sf.hibernate.exception.GenericJDBCException: could not insert: [com.atlassian.confluence.plugin.persistence.PluginData#3866628]
        at net.sf.hibernate.exception.ErrorCodeConverter.handledNonSpecificException(ErrorCodeConverter.java:90)
        at net.sf.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:79)
        at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
        at net.sf.hibernate.persister.AbstractEntityPersister.convert(AbstractEntityPersister.java:1331)
        at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:472)
        at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:436)
        at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:37)
        at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2447)
        at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2433)
        at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2390)
        at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2259)
        at com.atlassian.confluence.plugin.persistence.hibernate.HibernatePluginDataDao.saveOrUpdate(HibernatePluginDataDao.java:60)
        ... 121 more
Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1141938 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3250)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1940)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2693)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2102)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2395)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2313)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2298)
        at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
        at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:22)
        at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:462)
        ... 128 more

뭐.. 그래도 간단히 해결할 수 있는 문제다.
MySQL 의 max_allowed_packet 설정을 변경하자.

shell> mysqld --max_allowed_packet=32M

관련 링크 : http://confluence.atlassian.com/display/CONFKB/Getting+PacketTooBigException+Error+%27Packet+for+query+is+too+large%27

'System > JIRA, Confluence' 카테고리의 다른 글

JIRA와 TestLink 연동하기  (0) 2011.08.25
JIRA Plugin관리  (0) 2011.03.24

1. SVN 설치
[root@linux ~]# yum install -y subversion

2. SVN 사용자 추가
[root@linux ~]# adduser svn
[root@linux ~]# passwd svn
Changing password for user svn.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.

3. 저장소(Repository) 만들기
[root@linux ~]# svnadmin create --fs-type fsfs /home/svn/testRepos
[root@linux ~]# chown -R svn svn:svn /home/svn/testRepos

4. svn configuration
[root@linux ~]# vi /home/svn/testRepos/conf/svnserve.conf
---------------------------------------------------------------------------------------------
anon-access = read
auth-access = write
password-db = passwd

[root@linux ~]# vi /home/svn/testRepos/conf/passwd
---------------------------------------------------------------------------------------------
# username = password 식으로 작성
chigon = chigon

5. svn 기동
[root@linux ~]# svnserve -d -r /home/svn/

'QA > Test Automation' 카테고리의 다른 글

자동화에 extent report 적용하기  (0) 2018.01.22
Jenkins와 Sonar 연동하기  (0) 2012.07.19
Ant 로 Sonar 수행하기.  (0) 2011.04.12
Sonar 소개  (0) 2011.02.14
CI(Continuous Integration) 서버 구성안  (0) 2011.02.14

+ Recent posts