레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시

2023년 2월 3일 금요일

unix timestamp 13 digit compare

Intstant instant = Instant.ofEpochMilli(Long.parseLong(String timestamp));

Instant current = Instant.now();

instant.compareTo(current);


1 : t1 > t2

0 : t1 == t2

-1 : t1 < t2

2020년 11월 9일 월요일

element.click으로 브라우져의 새 탭이 열렸을 때 driver 제어 방법

 element.click 으로 같은 화면에서 UI가 갱신되는 게 아니라 새 탭이 열렸을 경우,

selenium driver에 알려줘야 한다.

그렇지 않으면 기존에 오픈 된 브라우져의 화면에서 element를 찾게 되어 no such element 에러 메시지를 보게 된다.


[How to]

//driver 제어를 위한 현재 열려있는 브라우져 확인
String parentWindow = driver.getWindowHandle();

element.click();


String childWindow = null;
for(String childs: driver.getWindowHandles()){
if(!childs.equals(parentWindow)){
childWindow = childs;
break;
}
}
driver.switchTo().window(childWindow);

2020년 11월 6일 금요일

Hamcrest Test Framework

 Hamcrest란?

test framework을 이용하여 단위 테스트 진행 시 assert를 유연하게 하기 위해 matcher를 이용하여 좀 더 쉽고 확장성 있는 assert를 하기 위해 만들어진 framework이다. 

Hamcrest는 처음부터 test framework과 통합되도록 설계되어 JUnit, TestNG와 함께 사용할 수 있다.


maven dependency

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>

Hamcrest code

assertThat(actual, is(equalTo(expedted);
assertThat(result, instanceof String);
assertThat(result, is(hasItem(anyOf(equalTo("x", equalTo("y"), equalTo("z"))))));

Hamcrest Matcher 

allOf - matches if all matchers match (short circuits)
anyOf - matches if any matchers match (short circuits)
not - matches if the wrapped matcher doesn’t match and vice
equalTo - test object equality using the equals method
is - decorator for equalTo to improve readability
hasToString - test Object.toString
instanceOf, isCompatibleType - test type
notNullValue, nullValue - test for null
sameInstance - test object identity
hasEntry, hasKey, hasValue - test a map contains an entry, key or value
hasItem, hasItems - test a collection contains elements
hasItemInArray - test an array contains an element
closeTo - test floating point values are close to a given value
greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo
equalToIgnoringCase - test string equality ignoring case
equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
containsString, endsWith, startsWith - test string matching

2020년 1월 17일 금요일

test 메소드 이름 알아오기

@Test
public void test(){
 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
 String methodName = stackTraceElements[1].getMethodName();
}

API Test에서 테스트 수행 시 profile 선택

1. mvn clean test -P ${env}
env = qa or release or stage

2. intelliJ 에서는






















2020년 1월 14일 화요일

HttpStatusCode 체크

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
 
 
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(new HttpGet(URL));
int statusCode = response.getStatusLine().getStatusCode();
logger.debug("StatusCode: {}", statusCode);

2019년 7월 18일 목요일

API Test 진행 시 profile 선택 관련 정리 - Maven profile, yaml, lombok

1. jenkins에서 profile 선택하여 빌드 및 테스트 수행
mvn clean test -P ${evn}
env : env는 jenkins의 string parameter나 choice parameter를 이용한다.
ex) evn = qa or release or stage

2. intelliJ에서는

3. 프로파일별 테스트 데이터 관리는 yaml 파일로 관리한다.
 
 yaml file 위치

testdata.yaml
userId : test
password : qwe123

TestData.java
TestData.java는 lombok library를 이용하여 코드를 간결화 한다.
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;

@Getter 
@Setter
public class TestData {
 private String userId;
 private String password;

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.DEFAULT_STYLE);
 }

 public TestData getTestData() {
  Yaml yaml = new Yaml();
  InputStream inputStream = TestData.class.getResourceAsStream("/testdata.yaml");
  return yaml.loadAs(inputStream, TestData.class);
 }
}

사용법

TestData testData = new TestData();
testData = testData.getTestData();
RestAssured.baseURI = testData.getTargetURL();

2019년 7월 8일 월요일

TestNG에 ExtentReport 적용하기

1. pom.xml dependency 추가

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

2. ExtentManager 추가

public class ExtentManager {
    private static ExtentReports extent;

    public static ExtentReports getInstance() {
        if (extent == null)
            createInstance();
        return extent;
    }

    //Create an extent report instance
    public static ExtentReports createInstance() {
        String reportFile = new File("target/result.html").getAbsolutePath();
        ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(reportFile);
        htmlReporter.setAppendExisting(true);
        htmlReporter.config().setTestViewChartLocation(ChartLocation.BOTTOM);
        htmlReporter.config().setChartVisibilityOnOpen(true);
        htmlReporter.config().setTheme(Theme.STANDARD);
        htmlReporter.config().setDocumentTitle(reportFile);
        htmlReporter.config().setEncoding("UTF-8");
        htmlReporter.config().setReportName(reportFile);

        extent = new ExtentReports();
        extent.attachReporter(htmlReporter);
        extent.setSystemInfo("Environment", "QA");
        TestData testData = new TestData();
        extent.setSystemInfo("Host Name", testData.getTestData().getUri());
        return extent;
    }
}

3. TestListener 추가

public class TestListner implements ITestListener {
    //Extent Report Declarations
    private static final Logger logger = LoggerFactory.getLogger(TestListner.class);
    private static ExtentReports extent = ExtentManager.createInstance();
    private static ThreadLocal<ExtentTest> test = new ThreadLocal<>();

    @Override
    public synchronized void onStart(ITestContext context) {
        logger.debug("Test Suite started!");
    }

    @Override
    public synchronized void onFinish(ITestContext context) {
        logger.debug("Test Suite is finished!");
        extent.flush();
    }

    @Override
    public synchronized void onTestStart(ITestResult result) {
        logger.debug(result.getMethod().getMethodName() + " started!");
        ExtentTest extentTest = extent.createTest(result.getMethod().getMethodName(),result.getMethod().getDescription());
        extentTest.assignCategory(result.getTestClass().getRealClass().getSimpleName());
        test.set(extentTest);
    }

    @Override
    public synchronized void onTestSuccess(ITestResult result) {
        logger.debug(result.getMethod().getMethodName() + " passed!");
        test.get().pass("Test passed");
    }

    @Override
    public synchronized void onTestFailure(ITestResult result) {
        logger.debug(result.getMethod().getMethodName() + " failed!");
        test.get().fail(result.getThrowable());
    }

    @Override
    public synchronized void onTestSkipped(ITestResult result) {
        logger.debug(result.getMethod().getMethodName() + " skipped!");
        test.get().skip(result.getThrowable());
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
        logger.debug("onTestFailedButWithinSuccessPercentage for " + result.getMethod().getMethodName());
    }
}

4. testng.xml에 추가
<suite name="TestNG Suite Name">
    <listeners>
        <listener class-name="com.xxxx.utils.listners.TestListner" />    
    </listeners>
    <test name="full_test">
         <packages>
             <package name="com.xxx.test.*" />
         </packages>
     </test>
</suite>

2019년 7월 2일 화요일

Jenkins Parameter를 java code로 받아오는 방법

1. Jenkins 구성에서 General탭의 "이 빌드는 매개변수가 있습니다." 체크
2. String parameter 등의 매개변수 추가
3. Build 옵션에서 Goal and options에 추가한 파라메터를 추가
-> clean test -D자바코드에서사용할파라메타=$젠킨스에서추가한파라메타
=> ex) clean test -DdeviceName=$deviceName -Dversion=$version

4. Java code에서는
String DEVICENAME = System.getProperty("deviceName");
String VERSION = System.getProperty("version");

2018년 8월 27일 월요일

TestNG에서 테스트 순서 제어하기


public class TestNGTest3 {
 
    @BeforeClass
    public void beforeclass(){
        System.out.println("@BeforeClass TestNGTest3");
    }
     
    @Test
    public void test7(){
        System.out.println("test7");
        Assert.assertTrue(true);
    }
     
    @Test
    public void test2() throws Exception{
        System.out.println("test2");
        Assert.assertTrue(true);
    }
     
    @Test
    public void test15() throws Exception{
        System.out.println("test15");
        Assert.assertTrue(true);
    }
     
    @AfterClass
    public void afterclass(){
        System.out.println("@AfterClass TestNGTest3");
    }
}
[결과]

@BeforeClass TestNGTest3
test15
test2
test7
@AfterClass TestNGTest3
PASSED: test15
PASSED: test2
PASSED: test7


public class TestNGTest1 {

    @BeforeClass

    public void beforeclass(){
        System.out.println("@BeforeClass TestNGTest1");
    }

    @Test
    public void test12() throws Exception{
        System.out.println("Test12");
        Assert.assertTrue(true);
    }

    @Test
    public void test5(){
        System.out.println("Test5");
        Assert.assertTrue(true);
    }

    @Test
    public void test3(){
        System.out.println("Test3");
        Assert.assertTrue(true);
    }

    @AfterClass
    public void afterclass(){
        System.out.println("@AfterClass TestNGTest1");
    }
}
[결과]

@BeforeClass TestNGTest1
Test12
Test3
Test5
@AfterClass TestNGTest1
PASSED: test12
PASSED: test3
PASSED: test5

[해결책]

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="TestNG Suite Name">
    <test name="TestNGTest" preserve-order="true">
        <classes>
            <class name="testng.TestNGTest1">
                <methods>
                    <include name="test3" />
                    <include name="test5" />
                    <include name="test12" />
                </methods>
            </class>

            <class name="testng.TestNGTest3">
                <methods>
                    <include name="test2" />
                    <include name="test7" />
                    <include name="test15" />
                </methods>
            </class>
        </classes>
    </test>
</suite>
[설명]
testng의 suite 파일에 preserve-order='true' 를 설정하고 해당 클래스의 test method의 순서를 지정해주면 된다.

[결과]
@BeforeClass TestNGTest1
Test3
Test5
Test12
@AfterClass TestNGTest1
@BeforeClass TestNGTest3
test2
test7
test15
@AfterClass TestNGTest3

※ 위 순서대로 사용하려면, dependsOnMethod를 사용하시면 안됩니다.

TestNG에서 2개 이상의 assert를 한꺼번에 처리하는 방법

개요

"@Test" 메소드에서 테스트 할 때 부득이하게 assert를 여러 번 해야 할 경우가 있다.
이 때 한꺼번에 처리해주지 않으면 첫번 째 assert에서 fail이 발생할 경우, 그 아래에 있는 assert 구문을 처리하지 않고 테스트가 종료되어 남아있는 assert 구문을 확인할 수 없다.
이를 해결하기 위한 방법을 정리한다.

내용

TestNG에서는 Hard assert / Soft Assert로 구분한다.
Hard Assert는 assert 시 fail이 발생하면 해당 테스트를 종료하는 것이고,
Soft assert는 assert 시 fail이 발생해도 로그에서는 fail이지만 테스트 결과는 pass로 해준다. 최종 결과를 확인하기 위해서는 아래와 같이 사용해야 한다.

Hard Assert


@Test
public void hardAssertTest(){
   Assert.assertFalse(2<1);
   System.out.println("Assertion Failed in Test 1");
   Assert.assertTrue(1<0);
   System.out.println("Assertion Failed in Test 2");
   Assert.assertEquals("Sample", "Sample");
   System.out.println("Assertion Passed in Test 3");
}
결과
Assertion Failed in Test 1
FAILED: hardAssertTest1
java.lang.AssertionError: expected [true] but found [false]
at org.testng.Assert.fail(Assert.java:94)
at org.testng.Assert.failNotEquals(Assert.java:513)
at org.testng.Assert.assertTrue(Assert.java:42)
at org.testng.Assert.assertTrue(Assert.java:52)
at testng.TestNGTest2.hardAssertTest1(TestNGTest2.java:13)
...
3번 line : PASS, 5번 line : FAIL이 발생하여 7번line의 assert를 하지 않고 hardAssertTest()의 테스트를 종료하고 빠져나온다. 테스트의 최종결과는 FAIL

Soft Assert 1


@Test
public void softAssertTest1(){
   SoftAssert sa= new SoftAssert();
   sa.assertTrue(2<1);
   System.out.println("Assertion Failed1");
   sa.assertFalse(1<2);
   System.out.println("Assertion Failed2");
   sa.assertEquals("Sample", "Failed");
   System.out.println("Assertion Failed3");
}
결과
Assertion Failed1
Assertion Failed2
Assertion Failed3
PASSED: softAssertTest1
assert는 fail이지만 테스트 결과는 PASS로 된다.

Soft Assert 2


@Test
public void softAssertTest2(){
   SoftAssert sa= new SoftAssert();
   sa.assertTrue(2<1);
   System.out.println("Assertion Failed1");
   sa.assertFalse(1<2);
   System.out.println("Assertion Failed2");
   sa.assertEquals("Sample", "Failed");
   System.out.println("Assertion Failed3");
   sa.assertAll();
}
결과
Assertion Failed1
Assertion Failed2
Assertion Failed3
FAILED: softAssertTest2
java.lang.AssertionError: The following asserts failed:
expected [true] but found [false],
expected [false] but found [true],
expected [Failed] but found [Sample]
at org.testng.asserts.SoftAssert.assertAll(SoftAssert.java:43)
at testng.TestNGTest2.softAssertTest2(TestNGTest2.java:54)
....
SoftAssert 객체를 생성한 후 - SoftAssert sa = new SoftAssert();
SoftAssert 객체로 assert를 모두 진행하고 난 뒤, 마지막에 "sa.assertAll()" 을 해주면 하나라도 fail이 발생 시 최종 테스트 결과는 FAIL로 된다.
assert를 모두 확인하고 테스트를 종료하므로 테스트 메소드에 assert 구문이 여러 개 일 경우 SoftAssert의 assertAll을 사용하자.

Logback 사용법

SLF4J란, Simple Logging Facade for Java의 약자로 Log4J의 개발자 Ceki Gülcü가 LogBack과 함께 개발한 Logging Facade 즉, 로깅에 대한 인터페이스 모음이라고 볼 수 있습니다.
LogBack이 바로 SLF4J의 Native 구현체이며 SLF4J를 사용하여 로깅 처리를 하면 실제 로그는 LogBack에서 출력하게 됩니다.
SLF4J에 대해 좀 더 자세히 알고 있으시면 공식 사이트(https://www.slf4j.org/) 에서 확인하세요
그리고 LogBack에 대한 메뉴얼은 https://logback.qos.ch/manual/index.html 에서 확인 가능합니다.

준비물

1.pom.xml에 logback 관련 의존성 추가

<dependencies>
   <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
      <exclusions>
         <exclusion>
            <artifactId>log4j</artifactId>
            <groupId>log4j</groupId>
         </exclusion>
         <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
         </exclusion>
         <exclusion>
            <artifactId>common-logging</artifactId>
            <groupId>common-logging</groupId>
         </exclusion>
      </exclusions>
   </dependency>
   <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>${logback.version}</version>
      <exclusions>
         <exclusion>
            <artifactId>log4j</artifactId>
            <groupId>log4j</groupId>
         </exclusion>
         <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
         </exclusion>
         <exclusion>
            <artifactId>common-logging</artifactId>
            <groupId>common-logging</groupId>
         </exclusion>
      </exclusions>
   </dependency>
</dependencies>
2. 설정파일(logback.xml) 추가
메인에 있는 코드가 실행될 때 적용하고 싶은 설정파일은  src/main/resource 밑에 두고, 테스트 단계에서 별도의 설정파일을 적용하고 싶으면 src/test/resource 밑에 둔다.
1) 로그 레벨
TRACE → DEBUG → INFO → WARN → ERROR 의 로그 레벨이 있고, 설정파일에서 설정 레벨 이상의 로그를 출력할 수 있다.
예) 레벨 : INFO로 설정하면 TRACE, DEBUG 레벨의 로그는 출력되지 않는다.

2) Appender
로그를 출력할 위치, 출력 형식등을 지정할 때 사용된다.
기본적인 Appender로는 ConsolAppender, FileAppender, RollingFileAppender가 있다.
ConsolAppender : 로그를 콘솔에 출력시킨다.
FileAppender : 로그의 내용을 지정된 파일에 기록한다.
RollingFileAppender : 지정된 패턴에 따라 로그가 파일에 기록하도록 하여 대량의 로그를 효과적으로 기록할 때 사용된다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%-5p] %C.%M[%L] %m%n</pattern>
      </encoder>
   </appender>
   <root level="debug">
      <appender-ref ref="STDOUT" />
   </root>
</configuration>
3. 코드 예

public class LogSample {
    private static final Logger logger = LoggerFactory.getLogger(LogSample.class);
    public static void main(String args[]){
  String stringMsg = "Test";
  int integerMsg = 123;
  logger.trace("trace");
  logger.debug("debug");
  logger.debug("debug {} {}", stringMsg, integerMsg);
  logger.info("info");
  logger.warn("warn");
  logger.error("error");
    }
}

결과

2016년 12월 1일 목요일

Junit MultiThread Test code


import org.junit.Test;

import junit.framework.TestCase;
import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;

public class TestThread extends TestCase{
 
 private static int THREAD_SIZE = 20;
 
 /*
  * Test class should have exactly one public zero-argument constructor이므로
  * TestCase 클래스를 extends 하고 GroboUtils의 클래스인 TestRunnable을 상속받은 클래스를 이너클래스로 사용하였다.
  */
 
 public class MultiThreadTest extends TestRunnable {
  
  private int i = 0;
  
  
  public MultiThreadTest(int i){
   this.i = i;
  }
  
  @Override
  public void runTest() throws Throwable {
   Thread.sleep(1000);
   
   System.out.println(Thread.currentThread().getName() + " : [" + i + "]");
  }
 }
 
 @Test
 public void test() throws Throwable{
  TestRunnable[] t = new TestRunnable[THREAD_SIZE];
  
  for(int index=0; index < THREAD_SIZE; index++){
   t[index]=new MultiThreadTest(index);
  }
  
  MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(t);
  mttr.runTestRunnables();
  
  System.out.println("main end.........................");
 }
}

2015년 7월 9일 목요일

Java MVC model

Observer
public interface Observer {
   public void update(int data);
}

Model
public class CalculatorModel {
 private int data;
 private ArrayList list = new ArrayList();
 
 public void addTwoNumber(int firstNumber, int secondNumber){
  data = firstNumber + secondNumber;
  notifyObservers();
 }
 
 public void registerObserver(Observer o){
  list.add(o);
 }
 
 public void notifyObservers() {
  for(Observer o : list){
   o.update(data);   
  }  
 }
}

Controller
public class CalculatorController implements ActionListener{
 private CalculatorModel model;
 private CalculatorView view;

 public CalculatorController(CalculatorModel model, CalculatorView view) {
  this.model = model;
  this.view = view;
  this.view.setCalculatorListener(this);
 }

 @Override
 public void actionPerformed(ActionEvent arg0) {
  try {
   int firstNumber = view.getFirstNumber();
   int secondNumber = view.getSecondNumber();
   model.addTwoNumber(firstNumber, secondNumber);
  } catch (RuntimeException e) {
   e.printStackTrace();
  }
 }
}

View
public class CalculatorView extends JFrame implements Observer{
 private JTextField firstNumber = new JTextField(10);
 private JLabel additionLabel = new JLabel("+");
 private JTextField secondNumber = new JTextField(10);
 private JButton calculateButton = new JButton("계산");
 private JTextField calcSolution = new JTextField(10);
 private JPanel calcPanel = new JPanel();

 public CalculatorView() {
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setSize(600, 200);
  setLayout(new BorderLayout());
  calcPanel.add(firstNumber);
  calcPanel.add(additionLabel);
  calcPanel.add(secondNumber);
  calcPanel.add(calculateButton);
  calcPanel.add(calcSolution);
  add(calcPanel, BorderLayout.CENTER);
 }

 public int getFirstNumber() {
  return Integer.parseInt(firstNumber.getText());
 }

 public int getSecondNumber() {
  return Integer.parseInt(secondNumber.getText());
 }

 public void setCalcSolution(int result) {
  calcSolution.setText(result +"");
 }

 public void setCalculatorListener(ActionListener listener){
  calculateButton.addActionListener(listener);
 }

 @Override
 public void update(int data) {
  setCalcSolution(data);
 }
}

Main Method
public class MVCTest {
 public static void main(String[] args) {
  CalculatorView view = new CalculatorView();
  CalculatorModel model = new CalculatorModel();
  model.registerObserver(view);
  
  @SuppressWarnings("unused")
  CalculatorController controller = new CalculatorController(model, view);
  view.setVisible(true);
 }
}