테스트 코드 필요성

  • 대부분의 서비스 회사가 테스트 코드에 관해 요구
  • 프로젝트형 코딩 테스트에 단위 테스트 필수조건 요구
  • 테스트 자동화 경험 우대

테스트 코드란?

** TDD vs 단위 테스트(Unit Test) **

TDD

  • 테스트가 주도하는 개발
  • 테스트 코드를 먼저 작성
  • 레드 그린 사이클
  1. 항상 실패하는 테스트를 먼저 작성: Red
  2. 테스트가 통과하는 프로덕션 코드를 작성: Green
  3. 테스트가 통과하면 프로덕션 코드를 리팩토링: Refactor

단위 테스트

  • TDD의 첫 번째 단계인 기능 단위의 테스트 코드를 작성하는 것을 의미
  • TDD와 달리 테스트 코드를 꼭 먼저 작성할 필요 X, 리팩토링 포함 X
  • 순수하게 테스트 코드만 작성하는 것을 의미

테스트 코드를 왜 작성해야 하는가?

  • 단위 테스트는 개발단계 초기에 문제를 발견하게 도와준다.
  • 단위 테스트는 개발자가 나중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인할 수 있다
  • 단위 테스트는 기능에 대한 불확실성을 감소시킬 수 있다.
  • 단위 테스트는 시스템에 대한 실제 문서를 제공한다. 즉, 단위 테스트 자체가 문서로 사용될 수 있다.

테스트 코드를 작성하면 좋은 점

  1. 톰캣을 내렸다가 다시 실행하는 일을 반복하지 않아도 된다.
  2. 눈으로 검증(수동검증)하지 않고 테스트 코드로 자동검증이 가능하다.
  3. 개발자가 만든 기능을 안전하게 보호해준다.( 규모가 큰 서비스에서 새로운 기능이 추가될 때, 기존 기능이 잘 작동되는 것을 보장해준다.)

테스트 코드 작성을 도와주는 프레임워크: xUnit

  • 가장 대중적인 테스트 프레임워크
  • 개발환경(x)에 따라 Unit 테스트를 도와주는 도구
  • JUnit - Java
  • DBUnit - DB
  • ... 등

BOJ_1996 프린터 큐

문제

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.

현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치 한다. 그렇지 않다면 바로 인쇄를 한다.
예를 들어 Queue에 4개의 문서(A B C D)가 있고, 중요도가 2 1 4 3 라면 C를 인쇄하고, 다음으로 D를 인쇄하고 A, B를 인쇄하게 된다.

여러분이 할 일은, 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 것이다. 예를 들어 위의 예에서 C문서는 1번째로, A문서는 3번째로 인쇄되게 된다.

입력

첫 줄에 테스트케이스의 수가 주어진다. 각 테스트케이스는 두 줄로 이루어져 있다.

테스트케이스의 첫 번째 줄에는 문서의 개수 N(1 ≤ N ≤ 100)과, 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N)이 주어진다. 이때 맨 왼쪽은 0번째라고 하자. 두 번째 줄에는 N개 문서의 중요도가 차례대로 주어진다. 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

출력

각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.

예제 입력 1

3  
1 0  
5  
4 2  
1 2 3 4  
6 0  
1 1 9 1 1 1

예제 출력 1

1  
2  
5

분석

  1. 아이디어
  • 문제에서 요구하는대로 구현
  • 해결 코드 주석 참조
  1. 복잡도
  • 주어진 문서들의 길이 시간 복잡도
  1. 자료구조

해결 코드

tc = int(input())

for _ in range(tc):
    n,m = map(int,input().split())
    docs = deque(list(map(int,input().split())))
    out_num=0

    while docs:
        doc_top = max(docs) # 중요도가 제일 높은 문서
        doc_1 = docs.popleft() # 가장 앞에 있는 문서
        m-=1 # 찾으려는 문서가 출력될 때까지, 왼쪽으로 이동하면서 탐색

        if doc_top == doc_1: # 가장 앞에 있는 문서가 중요도가 제일 높은 문서이면
            out_num+=1 
            if m < 0: # 찾으려는 문서가 중요도가 제일 높은 문서라 출력
                print(out_num)
                break
        else:# 2. 가장 앞에 있는 문서가 중요도가 제일 높은 문서가 아니라면
            docs.append(doc_1) # Queue의 가장 뒤에 재배치
            if m<0: # 찾으려는 문서가 중요도가 제일 높은 문서가 아니면서 가장 앞에 있어
                m = len(docs) - 1 # 가장 뒤에 재배치

'Etc > PS' 카테고리의 다른 글

BOJ_10026 적록색약 - Python3  (1) 2022.07.14
BOJ_2178 미로 탐색 - Python3  (0) 2022.07.14
BOJ_11279 최대 힙 - Python3  (1) 2022.07.11
BOJ_1927 최소 힙 - Python3  (0) 2022.07.11
BOJ_1018 체스판 다시 칠하기 - Python3  (0) 2022.07.01

1. 개발 도구 선정

1.1 인텔리제이(Intelij IDEA) 장점 및 기능

장점

  • 강력한 추천 기능
  • 다양한 리팩토링과 디버깅 기능
  • 높은 Git 자유도
  • 프로젝트 시작할 때 인덱싱을 하여 파일을 비롯한 자원들에 대한 빠른 검색 속도
  • HTML과 CSS, JS, XML에 대한 강력한 기능 지원
  • 자바, 스프링 부트 버전업에 맞춘 빠른 업데이트

커뮤니티(무료) 기능

  • 자바 개발에 대한 모든 기능 지원
  • Maven, Gradle과 같은 빌드 도구 기능 지원
  • 깃 & 깃허브와 같은 VCS(버전 관리 시스템) 기능 지원
  • 스프링 부트의 경우 톰캣과 같은 별도의 외장 서버 없이 실행 가능

HTML과 CSS, JS에 대한 지원은 하지 않아 다른 개발 도구 or 얼티메이트(유료) 이용

 

 

1.2 인텔리제이 설치 방법

1) 인텔리제이를 바로 내려받지 않고 젯브레인 툴박스 이용
2) 툴박스를 통해 인텔리제이 설치

 

 

툴박스: 젯브레인의 제품 전체를 관리해 주는 데스크톱 앱

  • 모든 제품군의 버전 관리와 JVM 옵션 등 조정할 수 있음
  • 새로운 버전이 나오면 툴박스 앱 안에서 업데이트를 바로 확인해서 진행 가능
  • [설정 -> Settings] : Maximun heap size 설정, 인텔리제이를 실행하는데, 어느 만큼의 메모리를 할당할지를 결정

 

1.3 인텔리제이에서 프로젝트 생성 방법

1) 프로젝트 유형 선택: 그레이들 (Gradle)

2) GroupId와 ArtifactId 등록

  • GroupId: 사용할 도메인를 거꾸로 이용 ex) com.dev-choee.service-a
  • ArtifactId: 프로젝트의 이름 ex) springboot2-webservice

3) 그레이들 옵션 선택: 인텔리제이의 기본 설정값

4) 프로젝트의 디렉토리 위치 선택

  • 기본적으로 ArtifactId가 프로젝트 이름
  • Project location에서 원하는 위치로 수정

 

1.4 그레이들 프로젝트를 스프링부트 프로젝트로 변경하기

build.gradle 파일 열어서 스프링 부트에 필요한 설정 추가

 

1) buildscript 코드 작성

buildscript{ 
    ext{ 
        springBoothVersion = '2.1.7.RELEASE' 
    }
    repositories{
        mavenCentral()
        jcenter() 
    }
    dependencies{  
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")        
    }
}

buildscript

  • 보통 별도의 외부 라이브러리를 가져와야 할 때 사용, repository와 dependencies로 구성

ext

  • build.gradle에서 사용하는 전역변수를 설정하겠다는 의미
  • 여기서springBootVersion 전역변수를 생성하고 그 값을 '2.1.7.RELEASE'로 설정

mavenCentral

  • 기본적으로 많이 사용
  • 단점: 본인이 만든 라이브러리를 업로드하기 위해 많은 과정과 설정 필요하여 공유가 안 되는 상황 발생

jcencer

  • 라이브러리 업로드를 간단하게 한 저장소
  • 인터넷의 jcenter 레파지토리 사용 (https://bintray.com/bintray/jcenter)
  • jcenter에 라이브러리를 업로드하면 mavenCentral에도 업로드될 수 있도록 자동화 가능

dependencies

  • 플러그인의 의존성을 받겠다는 의미
  • spring-boot-gradle-plugin라는 스프링 부트 그레이들 플러그인의 2.1.7.RELEASE를 의존성으로 받도록 설정

 

2) buildscript 이외 코드 작성

  • 앞서 선언한 플러그인 의존성들을 적용할 것인지를 결정하는 코드
apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'org.springframework.boot' 
apply plugin: 'io.spring.dependency-management' // !!필수!! 스프링 부트의 의존성들을 관리해 주는 플러그인
  • repositories : 각종 의존성(라이브러리)들을 어떤 원격 저장소에서 받을지를 결정
repositories { 
	mavenCentral() 
}

 

  • 프로젝트 개발에 필요한 의존성들을 선언하는 곳
dependencies { 
	implementation('org.springframework.boot:spring-boot-starter-web') 
	testImplementation('org.springframework.boot:spring-boot-starter-test') 
}

 

  • 인텔리제이에서는 메이븐 저장소의 데이터를 인덱싱해서 관리하기 때문에 의존성 자동완성 가능(ctrl+space)
  • 버전을 명시하지 않아야만 위에서 작성한 "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"의 버전을 따라간다.
  • 책에서는 compile(), testCompile을 사용하지만, implementation을 사용.

Gradle 의존성 옵션: Compile vs implemaetation

 

[Gradle] implementation vs compile

서론 Gradle dependency 관련해서 검색을 하다보면, 어떤 글에서는 implementation을 사용하고 어떤 글에서는 compile을 사용하는 경우가 있다. 사실 어떻게 사용해도 돌아가긴 해서, 음... 무슨 차이지?하고

bluayer.com

3) build.gradle 변경 반영
인텔리제이 오른쪽 하단 알럿의 Enable Auto-import 클릭하여build.gradle 변경이 있을 때 마다 자동 반영되도록 설정

 

4) 의존성 확인
오른쪽 Gradle 탭을 클릭하여 의존성들이 잘 받아졌는지 확인

 

 

1.5 인텔리제이에서 깃과 깃허브 사용하는 방법

  • VCS(버전 관리 시스템) 선택: Git
  • Git의 원격 저장소 서비스 선택: Github

인텔리제이에서 깃허브 연동

1) Ctrl + Shift + A : Action 검색창 열기
2) share project on github 검색
3) 깃허브 로그인
4) Repository name 설정 후 등록 ( 최초 git ingnore 설정 No)
5) 첫 커밋 팝업창에서 .idea 디렉토리 제외한 후 커밋 ( 실행시 자동으로 생성되는 파일들이므로 깃허브 올릴 필요 없음 )
6) .gitignore파일을 사용하여 .idea 폴더를 앞으로의 모든 커밋 대상에서 제외 처리

  • 인텔리제이에서는 .gitignore 파일에 대한 기본적인 지원이 없음
  • 플러그인에서 .gitignore 지원

 

.ignore 플러그인
지원 기능

  • 파일 위치 자동완성
  • 이그노어 처리 여부 확인
  • 다양한 이그노어 파일 지원(.gitignore, .npmignore, .dockerignore 등)

설치 방법

1) Ctrl + Shift + A : Action 검색창 열기
2) plugins 검색
3) Marketplace 에서 .ignore 설치
4) 인텔리제이를 다시 시작해서 설치한 플러그인 적용 ( 반드시 재시작해야만 함)
5) .gitignore 파일 생성: 프로젝트 이름을 선택한 뒤, 마우스 오른쪽 or Alt + Insert로 New(생성목록) 확인하여 .gitignore 파일 생성
6) 이그노어 처리 후 깃허브에 .gitignore 파일을 푸시하여 반영

이그노어 처리

  • 인텔리제이에서 자동으로 생성되는 파일들을 모두 이그노어 처리
  • .gradle .idea

그래프

여러 개체들이 연결되어 있는 자료구조

탐색

특정 개체를 찾기 위한 알고리즘

대표적 문제 유형

  1. 경로탐색 유형 (최단거리, 시간)
  2. 네트워크 유형 (연결)
  3. 조합 유형 (모든 조합 만들기)

 

DFS(Depth-Firsh Search) 깊이 우선 탐색

  • 한 놈만 끝까지 패는 유형

구현 방법

  • 재귀함수가 가장 일반적
  • 한 가지 방법을 끝까지 다 해보고 다음 방식 동작

 

BFS(Breadth-First Search) 너비 우선 탐색

  • 여러 놈을 한대씩 때리면서 가는 유형

구현 방법

  • Queue / LinkedList 사용이 가장 보편적

 

DFS/BFS 알고리즘 판단 방법

  • 자신있는 알고리즘으로 탐색
  • DFS의 장점: 하나의 조합을 완성해서 정답과 비교하는 방식임으로 동작 검증이 쉽다
  • BFS의 장점: 시간복잡도가 낮다(효율성 TC에 유리)

 

참조

'CS > DSA' 카테고리의 다른 글

[자료구조] Array (배열) & LinkedList (연결리스트)  (0) 2022.08.01

알고리즘: 완전탐색(Brute Force)

  1. 입력: n, m을 입력받아 n 줄의 문자열을 리스트에 저장
  2. 8×8 크기의 체스판 모두 탐색 => n-7, m-7 범위에서 모두 탐색
  3. 첫 칸이 B, W 인 경우 모두 탐색
  4. 2차원 배열 좌표 합의 나머지 규칙으로 인접한 사각형이 같은 색인 경우 칠하는 개수 카운팅
  5. B, W 로 시작하는 경우 중 작은 값 n-7, m-7 범위 카운팅 리스트에 저장
  6. 출력: 카운팅 리스트에서 최소값을 출력

해결 코드

n,m=map(int,input().split())
board=list()
cnt=list()

for _ in range(n):
    board.append(input())

for i in range(n-7):
    for j in range(m-7):
        blackCase=0
        whiteCase=0
        for a in range(i,i+8):
            for b in range(j,j+8):
                if (a+b)%2==0:
                    if board[a][b]!='B': 
                        blackCase+=1
                    if board[a][b]!='W': 
                        whiteCase+=1
                else:
                    if board[a][b]!='W': 
                        blackCase+=1
                    if board[a][b]!='B': 
                        whiteCase+=1
        cnt.append(min(blackCase,whiteCase))
print(min(cnt))

'Etc > PS' 카테고리의 다른 글

BOJ_10026 적록색약 - Python3  (1) 2022.07.14
BOJ_2178 미로 탐색 - Python3  (0) 2022.07.14
BOJ_11279 최대 힙 - Python3  (1) 2022.07.11
BOJ_1927 최소 힙 - Python3  (0) 2022.07.11
BOJ_1996 프린터 큐 - Python3  (0) 2022.07.08

+ Recent posts