수업 시간에 배웠던 JUnit5 단위 테스트를 작성해볼까 한당!ㅇㅅㅇ

 

우선! 간단하게 단위 테스트가 무엇인지 정리하고 실습을 할 것이다. 

(진짜 간단하게........)

 

1. 단위 테스트  

단위 테스트는 가장 기본적인 테스트 활동이다. 

 

1-1) 단위 테스트 특징

  • 개발 환경에서 수행
  • 단위(주로 module, component, sub program, class, method) 간의 연계는 고려하지 않으며 단위 내부의 결함 제거가 목적
  • 주로 구조 기반 테스트 설계 기법을 사용 (Whitebox Test)
Q) Whitebox vs Blackbox ??

소프트웨어 테스트 방법론 2가지를 소개하면 화이트박스와 블랙박스이다.

Whitebox = 구조 기반 : 구조(structure based)를 기반으로 하는 테스트로, 내부구조를 분석해 테스트 케이스 도출. (단위 테스트는 개발 환경에서 수행하니까 여기에 해당)

Blackbox = 명세 기반 : 사용자가 요구하는 기능을 측정하기 위해서 내부구조를 모르는 상태로 테스트를 진행하는 방법 

경험 기반 : 테스트 엔지니어의 경험, 지식과 직관에 기반하여 테스트 케이스 도출

 

<whiteBox 테스트>

화이트 박스 테스팅을 하기 위해서는 프로그램 내부 구조를 분석해야 한다. 

그리고 테스트하려는 단위를 결정할 때 프로그램 코드상의 수행경로를 정의하고, 그 경로를 커버하는 테스트 케이스를 수행하면 된다. 

 

코드 적용 수준, 즉 수행범위(레벨)에 따라 구문 커버리지, 결정 커버리지, 조건 커버리지 등  있다.

 

 

 

1-2) 단위 테스트 목표

그러면 이번에 실습해볼 구조 기반인 단위 테스트의 목표는 무엇인가!?

 

  • 프로그램상의 모든 경로들을 최소한 한 번은 테스트하는 것

 

2. JUnit5 실습 

실습을 해볼 것은 자바에서 동작하는, 아키텍처가 필요없는 하나의 모듈이 하나의 프로그램이 되는 요구사항이 있었고, 

이것을 가지고 단위 테스트를 할 것이다. 

 

 

2-1) 테스트 대상 - 삼각형 종류 

 

Q) 삼각형의 변의 길이를 나타내는 세 정수 값을 입력하여 삼각형이 부등변 삼각형인지, 이등변 또는 정삼각형인지 보여준다.

 

먼저 소스 코드를 작성한다.

> 코드 참고

더보기
import java.util.Scanner;

public class TriangleProperty {

  public static void main(String[] args) {

    int a, b, c;
    String result;

    Scanner scanner = new Scanner(System.in);
    a = scanner.nextInt();
    b = scanner.nextInt();
    c = scanner.nextInt();

    scanner.close();

    result = classifyTriangle(a, b, c);

    System.out.println(result);
  }

  public static String classifyTriangle(int a, int b, int c) {

    if ((a + b <= c) || (a + c <= b) || (b + c <= a))
      return "Invalid";

    if (a == b && b == c)
      return "정삼각형";

    if (a == b || b == c || a == c)
      return "이등변삼각형";

    return "비등변삼각형";
  }

}

 

 

앞에서 말한

"그리고 테스트하려는 단위를 결정할 때 프로그램 코드상의 수행경로를 정의하고, 그 경로를 커버하는 테스트 케이스를 수행하면 된다. "

=> 여기서 세 정수를 입력 받아 정삼각형인지 이등변, 비등변삼각형인지 알아보는 수행경로를 정의했고, 

     classifyTriangle 메소드 단위를 테스트할 것이다.

 

 

 

JUnit5 도구를 사용할 것인데 JDK에 설치되어 있다.

프로젝트 오른쪽 버튼을 눌러서 Build Path > Add Libraries 눌러서  JUnit 선택하면 된다.

 

2-2) 테스트 실행 

 

그리고 작성한 TriangleProperty.java 클래스 파일에 오른쪽 버튼을 눌러서 JUnit Test Case 선택해서 생성해준다.

 

 

> 코드 참고

더보기
package communication;

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;


class TrianglePropertyTest {

  @Test
  final void 정삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(1, 1, 1);
    assertTrue(result.contentEquals("정삼각형"));
  }

  @Test
  final void 이등변삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(2, 2, 3);
    assertTrue(result.contentEquals("이등변삼각형"));
  }

  @Test
  final void 삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(1, 2, 3);
    assertTrue(result.contentEquals("Invalid"));
  }

  @Test
  final void 비등변삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(3, 4, 5);
    assertTrue(result.contentEquals("비등변삼각형"));
  }


}

 

 

알아보기 쉽도록 일단 메소드명을 한글로 작성했다. 

이렇게 코드를 작성해주고 아래처럼 Coverage As > JUnit Test 실행한다.

 

테스트가 잘 되었다면 아래처럼 파란색으로 표시가 된다. 틀렸을 경우에는 빨간색으로 표시가 된다.

>코드 참고

더보기
package communication;

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;


class TrianglePropertyTest {

  @Test
  final void 정삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(1, 1, 1);
    assertTrue(result.contentEquals("정삼각형"));
  }

  @Test
  final void 이등변삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(2, 2, 3);
    assertTrue(result.contentEquals("이등변삼각형"));
  }

  @Test
  final void 삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(1, 2, 3);
    assertTrue(result.contentEquals("Invalid"));
  }

  @Test
  final void 비등변삼각형테스트() {

    String result = TriangleProperty.classifyTriangle(3, 4, 5);
    assertTrue(result.contentEquals("비등변삼각형"));
  }


}

 

 

아래 Coverage를 봐도 TrianglePropertyTest.java 보면 커버리지가 100%된 것을 확인할 수 있다. 

되도록이면 커버리지가 100% 가깝게 해주는게 좋다.

 

여기서!!!!

TriangleProperty.java를 보면 57.6% 밖에 안되어있는데 신경쓰지 않아도 된다. 

위에 빨간 부분들은 적용 범위가 아니기 때문에..

그리고 또 하나!!!더!!

노란색으로 표시되어있는 것은 모든 경우의 수를 충족하지 않았을 경우이다. 

 

노란색을 초록색으로 바꾸고 싶다면 아래처럼 모든 경우를 다 작성해서 테스트하면 된다.!

 

 

오른쪽 Add 버튼 눌러서 import 하고 싶은 프로젝트를 추가해주면 된다!

회사에서 자바 프로젝트로 채팅 프로그램을 만들었다. 

swing을 이용한 소켓 채팅 프로그램........

처음에 스윙이 뭐지?하면서 코드가 어색했는데 지금은 너무 익숙하다ㅋㅋㅋ 

 

너무 힘들었던 3가지를 기록해야겠따..흑흑

 

1) 채팅할 때 화면에 나오는 나는 오른쪽, 친구는 왼쪽 정렬이 너무 어려웠다.
하아ㅏㅏㅏㅏ 이걸로 거의 일주일은 날린 것 같다.

처음에 JTextArea를 사용했다. 그런데 왼쪽, 오른쪽 정렬이 따로 되지 않는 것과 이미지는 불가능하다는 것.

그래서 구글링하다가 JTextPane을 발견했다. 이것을 사용하면 될 것 같은데 정보가 많이 없었다..ㅠㅅㅠ

일주일동안 삽질하다가 인턴 같이 하는 오빠가 메소드 하나하나씩 분석해가면서 성공시켰다.!!!!!!!!!!!!!!!!!!!!!!

덕분에 잘 적용할 수 있었다. 고마워요...

 

아 지금 이거 적다가 나머지 힘들었던 2가지가 기억나질 않는다. (큰일) 2가지만 적어야지..

 

   

2) 그룹채팅이 아니라 1대 1 채팅 만든 것. 

이것저것 참고해가면서 채팅 프로그램을 만드는데 보통 다 그룹채팅 형식이었다.
(서버쪽에서 연결된 모든 클라이언트를 저장하는데, 메시지를 받고 보낼 때 모든 클라이언트한테 전송함 - 조건을 주지 않으므로 더 간단함.)    
그래서 처음 소켓 통신 성공시키고 대화하는데 웃겼다. 내 아이디로 로그인해서 A친구 채팅방에 글을 쓰고 전송 누르면, A친구한테만 전달되는 것이 아니라 열려 있는 모든 채팅방 친구들한테 다 전달이 된다.ㅋㅋㅋ

하지만 내 채팅은... 카톡처럼 친구 리스트(?)를 누르면 그 친구랑 대화하도록 GUI를 만들어서 그럴 수 없다구,,,  1:1 이어야 한다구....  
결론은 성공시켰지만 생각보다 간단하지 않았다. 채팅창의 정보도 저장하고 있어야하고 보내는 사람, 받는 사람 비교
도 필요하고! 아 그냥 직접 해봐야 알 수 있는 것..

 

 

 

코드 정리를 더 완벽하게 하고 싶은데 여기서 마무리하려고 한다. 

시간을 길게 가진다고 되는 것이 아니라는 걸 너무 느꼈기 때문에...@!@!

나중에 폭풍성장하고 그때 다시 와서 보면 더 완벽하게 할 수 있지 않을까 싶다ㅎㅎㅎ


KEVotingTalk

  • 자바 스윙을 이용한 소켓 채팅 프로그램
  • 사용 기술 : JAVA
  • 설명 : 1 대 1 채팅 KEVotingTalk입니다. GUI를 구현하기 위해 swing을 이용했고 서버와 클라이언트는 소켓 통신을 통해 연결됩니다. 마지막으로 회원관리를 위해 MySQL DB 사용했습니다.
  • github : github.com/YuJinSong412/KEVotingTalk

 

  • 클래스 설명
    • client.datacommunication.ClientSocket.java : 클라이언트 측 송수신 파일
    • client.frame.ChatWindowFrame.java : 채팅 창 파일
    • client.frame.ChatWindowPanel.java : 채팅 화면 파일
    • client.frame.ErrorMessagePanel.java : 에러 화면 파일
    • client.frame.FriendListPanel.java : 친구 목록 화면 파일
    • client.frame.IndexPanel.java : 메인 화면 파일
    • client.frame.JoinMembershipPanel.java : 회원가입 화면 파일
    • client.frame.LoginPanel.java : 로그인 화면 파일
    • client.frame.MainFrame.java : 애플리케이션 창 파일
    • client.frame.MainPanel.java : 애플리케이션 시작 화면 파일
    • client.ClientLaunch.java : 클라이언트 실행 파일
    • controller.Controller.java : java와 DAO 사이의 중간 역할 파일
    • enums.AlignEnum : 채팅창 화면 오른쪽, 왼쪽 정렬 상수 파일
    • enums.CommonWord : 애플리케이션 상수 파일
    • server.datacommunication.Message.java : 메시지 정보 파일
    • server.datacommunication.ServerHandler.java : 서버 측의 송수신 파일
    • server.userdb.User.java : 사용자 정보 파일
    • server.userdb.UserDAO.java : DB의 데이터 접근 파일
    • server.userdb.userDB.sql : MySQL의 쿼리 파일
    • server.ServerLaunch.java : 서버 실행 파일
    • util.ColorSet.java : 애플리케이션 색깔 모음 파일
    • util.CommonPanel.java : 애플리케이션 기본 화면 파일
    • util.JFrameWindowClosingEventHandler.java : 창 닫는 이벤트 파일
    • util.MainPanelButton.java : 애프릴케이션 시작 버튼 파일
    • util.UseImageFile.java : 애플리케이션 이미지 파일
    • util.UserInfoPanel.java : 애플리케이션 이미지 파일
    • util.UserProfileButton.java : 친구 버튼 파일

 


ScreenShot

 

첫 화면

 

 

 

회원가입, 로그인 화면

 

 

 

에러 화면

 

 

 

메인 화면

 

 

 

나와의 채팅

 

 

 

 

이미지 첨부

 

 

1:1 채팅

 

자바 스윙(java swing)을 이용한 채팅 프로젝트를 하고 있는데 모든 클래스에 노란줄이 있다.. 

사실 바로 전에 계산기 만들 때도.. 계속 함께 했다... 

대체 왜 뜨냐고!!! 

 

>> serializable과 관계가 있다.

 

 

그래도 일단 해결 방법을 앞에다가 적어야지~~

#노란 경고메시지 없애는 해결 방법

1. Add default serial version ID

2. Add generated serial version ID

3. Add @SuppresWarnings 'serial' to Object

그냥 3개 중 선택해서 눌러주면 된다.ㅇㅅㅇ

 

 

이제 이유를 알아볼 차례!!

# serializable(직렬화)

1. serializable(직렬화)가 무엇이지?

- 객체의 데이터를 일렬로 늘어선 연속적인 바이트로 변경하는 것 

 

 

자바는 메모리에 생성된 객체를 파일이나 네트워크로 입출력할 수 있다.  그런데 객체는 문자가 아니기 때문에 바이트 기반 스트림으로 입출력해야 한다. 

 

왜냐하면 자바에서 데이터는 stream을 통해 입출력되는데(java.io 패키지에서 제공), 스트림 클래스는 크게 두 종류로 구분된다.

1. 바이트 기반 스트림 -> 그림, 멀티미디어, 문자 등 모든 종류 데이터

2. 문자 기반 스트림 -> 문자

 

따라서 객체를 출력하기 위해서는 객체의 데이터를 일렬로 늘어선 연속적인 바이트로 변경해야 하는데, 이것을 객체 직렬화라고 한다.

그리고 전송된 객체를 입력 스트림으로부터 읽어들인 것을 복원하는 것을 deserialization(역직렬화)라고 한다.

 

이것은 java.io.Serializable 이라는 인터페이스로 구현되어 있고,

직렬화하려는 클래스에 Serializable 인터페이스를 implements 하게 된다. 

그런데 Serializable 인터페이스를 implements 하게 되면 노락색 경고 메시지가 나온다.

The serializable class MainFrame does not declare a static final serialVersionUID field of type long

나처럼 무시해도 상관없지만..ㅎ 이유는 알아야 하니깐...

 

# Warning 이유

serialVersionUID는 직렬화에 사용되는 고유 아이디인데, 객체를 직렬화할 때 serialVersionUID도 저장이 된다.

만약 선언하지 않으면 JVM에서 default로 자동 생성된다. 

따라서 선언하지 않아도 동작하는데 문제가 없지만, 불안하기 때문에 명시적으로 선언할 것을 권장하는 것이다.

 

고유 아이디? 왜 불안한가?

모든 class는 UID를 가지고 있는데 내용이 변경되면 UID값도 변경된다. 

만약 직렬화하여 통신하는데 UID 값이 바뀌게 되면 다른 class로 인식하기 때문에 명시를 해주는 것이다.

 

 

그래서 노란색 경고 메시지가 뜨는 것이고, 

내가 작성한 클래스에 extends한 상위 클래스나 implements를 따라가보면 implements Serializable 부분을 발견할 것이다.

 

 

한번 찾아보기로 했다.

1. ctrl 를 누른 상태로 JFrame 클릭하면 JFrame 클래스로 이동한다. 

 

2. implements serializable가 없어서 Frame 도 보고 implements한 WindowConstants, Accessible.. 전부 보다가 TransferHandler를 눌렀는데!!!!!!!

 

 

3. 발견했다..!

그런데 TransferHandler 뭐하는 놈이지...

위로 올려서 package를 보니까 "package javax.swing; 이네??

docs 보니까 이 클래스는 Swing의 컴포넌트와........생략하도록 하자. 

 

나는 3번으로 해결했다!

macOS 에서 oracle를 사용하려면 복잡하지만 MySQL은 간단하다고 한다. 

그래서 MySQL을 설치하고 사용할 것!

 

macOS 용 패키지 관리자 Homebrew를 이용하여 설치할 것이다.

Homebrew를 이용하면 설정 과정이 단순화되며, 환경변수 설정이 필요없고 관리가 용이하다고 한다. 

 

 


1. MySQL 설치 

 

1. 먼저 터미널을 열어서 brew update 명령어를 이용해서 최신 버전으로 업데이트하고 

  brew install mysql 명령어를 이용하여 최신버전 설치한다.

(아무것도 뜨지 않고 커서만 깜빡여도 인내심을 가지고 기다릴 것.. 단지 느린 것 뿐..)

사실 처음에 brew update 명령어 입력을 했는데 error 표시도 없이 커서만 깜빡이고 있어서 놀랬다.. 왤케 느린거니..!!

그래서 ctrl + C 를 눌러서 취소하고 그냥 brew install mysql 입력해줬더니 또 깜빡깜빡..ㅇㅅㅇ

몇 분 기다리니까 알아서 실행해주었다.ㅎㅎㅎㅎ

 

 

 

 

2. brew list 명령어를 입력하여 설치 목록에 mysql이 있는지 확인하기

 

 

 

 

3. mysql.server start 명령어를 입력하여 MySQL 서버 실행

 

 

 

 

4.이제 mysql_secure_installation 명령어로 MySQL 설정을할 것이다.

"Press y|Y for Yes, any other key for No:"

비밀번호 설정에 대한 것이다.

 

Yes - 복잡한 비밀번호 설정

No - 쉬운 비밀번호 설정

 

선택하고 앞으로 사용할  root 계정의 비밀번호를 입력한다.

 

 

 

 

5. 이어서 나오는 설정을 해준다.

순서대로 

 

1. "사용자 설정"

Yes - 접속하는 경우 "mysql -u root"처럼 -u 옵션 필요

No - 접속하는 경우 "mysql"처럼 -u 옵션 불필요

 

2. "다른 IP에서 root 아이디로 원격접속 설정"

Yes - 원격접속 불가능

No - 원격접속 가능

 

3. "test 데이터베이스 설정"

Yes - Test 데이터베이스 제거

No - Test 데이터베이스 유지

 

3. "변경한 권한을 테이블에 적용하는 설정"

Yes - 적용

No - 적용 X

(무조건 Yes로 하라고 한다!)

 

 

이렇게 다 설정해주면 마지막에 "All done!" 이 화면에 딱! 나온다. (유휴)

 

 

 

6. 이제 mysql -u root -p 명령어 이용해서 비밀번호 입력하고 로그인 한다. 

(mysql> 표시를 확인할 수 있다. root 계정으로 로그인)

로그아웃 명령어는 exit 이나 quit

MySQL 서버 종료 명령어는 mysql.server stop

 

 

 

 

2. user 생성과 권한 부여 & 일반 계정으로 접속 

1. mysql -u root -p 명령어를 이용하여 root 계정으로 접속한다.

그리고 user를 생성하는 명령어를 작성한다.

예를 들어,

아이디 : yujinEE  비밀번호 : 1234 로 하고 싶다면 

create user 'yujinEE'@'%' identified by '1234';

'%' 는 모든 원격지에서 접속 권한 허용
접근 허용하고 싶지 않으면 localhost로 변경

 

예) '199.198.%' 로 하면 IP 주소가 199.198.X.X 로 시작되는 모든 IP에서 원격 접속을 허용한다는 의미

 

 

 

2. 권한 부여는 특정 데이터베이스에만 권한을 줄 수도 있고, 특정 권한만 줄 수도 있지만

일단 나는 모든 데이터베이스의 모든 테이블에 대한 권한 부여를 할 것이다.

grant all privileges on *.* to 'yujinEE'@'%';

이렇게 작성해주고 변경한 권한을 즉시 반영시켜주는 명령어도 마지막으로 작성해준다.

FLUSH PRIVILEGES;

 

 

 

 

3. 생성과 권한 부여를 했으니 yujinEE 계정으로 접속을 해볼 것이다.

mysql -u yujinEE -p

 

 

 

 

4. yujinDB를 생성할 것이다. 

 

 

 

3. eclipse에 MySQL 연결

1. 일단

https://dev.mysql.com/downloads/file/?id=476197

에서 connector/J 다운받는다. 

(mysql-connector-java-5.1.46.tar.gz 버전)

mysql-connector-java-5.1.46-bin.jar 저것을 사용할 것임!!

 

 

 

 

2. 이클립스 하단에 "Data Source Explorer"가 보이지 않으면 

Window > Show View > Data Source Explorer 선택하면 하단에 나온다.

아니 근데 난 왜 없어..?

Other 눌러서 찾아봤는데도 없잔슴?!

 

방법은 

[Help] - [Install New Software..] - work with에 

눌러서 Database Development 선택하면 된다.

그리고 그 후에 restart 되니까 기다릴 것!!

 

이제 다시 확인해보면 있다!!

Window > Show View > Other... > Data Management > Data Source Explorer를 선택해준다.

 

 

 

 

3. Data Source Explorer 화면을 보면 Database Connections 가 보일 것이다.

우클릭하여 New를 선택한다.

그러면 아래 화면이 나오는데 MySQL를 선택하고 적당한(?)이름을 적어준다.

 

 

Next 버튼을 누르고 아래 화면 그대로 보면 JAR List에 어쩌구쩌쩌구.jar 이 보일 것이다.

선택해서 Remove JAR/Zip 버튼을 눌러 삭제하고 

Add JAR/Zip... 눌러서 아까 다운 받은 mysql-connector-java-5.1.46-bin.jar를 추가해준다.

 

그리고!!

알맞게 적어주고 Test Connection 눌러줬을 때 Ping Success!! 뜨면 성공한 것이다!!

 

 

4. java 프로젝트 만들어서 DB 연결 확인하기

 

먼저 해당 프로젝트에서 Build Path >Configure Build Path.. 눌러서

 

Libraries 탭에 들어가서 Add External JARs... 선택하여 mysql-connector-java-5.1.46-bin.jar 추가해준다.

그리고 코드 작성 후 실행해주면 된다!

 

 

성공~~~!!!!!!

이제 본격 원하는 작업을 해야겠다!

+ Recent posts