Yo-mi 2023. 8. 31. 03:09

Test and Enhancement: 정해진 기법은 아니다. 회사마다 다르다.

개발은 잘 작동하면 끝인가?

1.     Reliability(신뢰성): 믿을 수 있나? 24시간, 365일 잘 동작하는가?

2.     Sustainability(지속 가능성): 한번 만들면 계속 사용됨, 유지보수 측면에서 계속 사용가능한가?

3.     Performance(성능): 더 빠르게, 더 적은 메모리 관리, 더 적은 리소스

4.     Readability(가독성): 다른 사람이 코드를 읽을 때 쉽게 읽을 수 있는가?

 

TDD에 대해 설명해라

TDD는 test 프로그램을 만들고 test를 통과하는 것을 목표로 한다.

일단은 주어진 입력에 맞춰 test를 통과하는 코드를 짜자. 주어져 있는 요구사항에 충실해라.

애자일 스크럼이라면 우리가 이번 스프린트에서 달성해야 할 백로그 존재하고, TDD에서는 요구사항이 있다.

 

What is TDD?

TDD란 요구사항을 담은 테스트 코드를 작성하고 이 테스트 코드를 통과하는 product 코드를 짜는 기법이다. 일단은 주어진 입력에 맞춰 test를 통과하는 코드를 짜는 것이 목적이다.  요구사항들을 쪼개 여러 사이클을 돌도록 하고 테스트 코드와 product 코드는 사이클을 돌면서 점점 커진다.

테스트 기반 개발은 익스트림 프로그래밍의 개념과는 관련이 있다.

프로그래머는 또한 이 개념을 이전 기술로 개발된 레거시 코드를 개선하고 디버깅하는 것에 적용한다.

 

TDD과정

1.     이번 사이클의 요구사항을 테스트하는 코드를 먼저 짠다. 내가 만들 프로그램의 함수, 클래스, 메소드를 호출하고 원하는 결과가 나오는 지를 test하는 코드를 먼저 짠다. 이 과정을 통해 본인이 짜야 할 프로그램에 대한 이해가 더 견고해질 수 있다. 또한 아무것도 없는 상태에서 test 코드를 짜므로 객관성을 유지할 수 있다. (본인이 짠 함수나 클래스에 애정이 생겨 의도치 않게 방어를 하는 경우가 있음) 테스트 코드 개발자와 product 코드 개발자를 다른 사람으로 한다면 더 객관적일 수 있다. 이를 pair programming이라고 한다.

2.     테스트 코드를 실행해 성공하는 지 실패하는 지를 본다. 만약 성공할 경우 다시 테스트 코드를 짠다. 통과되는 것이 사실 이상하다.

3.     실패할 경우 test 코드를 통과하기 위한 product 코드를 작성한다. 이 과정에서 작성되는 코드는 완벽하지 않아도 된다. Test를 통과하는 코드를 작성하는 것이 최우선이고 구조를 다듬고 성능을 높이는 refactoring은 나중에 한다.

4.     작성한 product 코드에 대해서 테스트를 실행하고 테스트 실패 시 다시 product 코드를 작성한다.

5.     테스트를 모두 통과하면 코드를 refactor, 청소한다. 이러면 한 사이클이 끝나는 것이다. 예를 들어 자주 등장하는 메소드들을 묶어 클래스를 만들거나 (가독성을 위해) 이름을 정리한다, duplication을 제거한다.

6.     이후 사이클에서는 기존의 테스트 코드, product 코드에 새로운 요구사항에 대한 코드를 추가하는 방식이다. 따라서 test 코드가 점점 커진다. 이전 사이클의 테스트 코드는 그대로 놔두고, 새로운 요구사항을 만족시킬 테스트 코드를 추가한다. 한 사이클마다 전체 기능의 3%, 6%씩 만들어 나가는 것이다.

 

TDD와 Agile의 관계

Cycle을 한번 통과하면 요구사항에 대한 test를 마친다. 자연스럽게 cycle-based로 돌아가는 것이 agile의 sprint 기법하고 잘 맞는다. Sprint의 백로그를 TDD의 요구사항으로 볼 수 있다. 테스트 결과를 보고서로 제출하는 것이 document를 줄이고자 하는 agile과 알맞다.

Test code자체가 document가 될 수 있다. (가독성이 좋다.)

 

다른 시각에서의 TDD

Refactoring 단계를 크게 보는 경우도 있다. Refactoring은 성능을 끌어올리는 단계이다. 이 단계에서 반복적으로 발생하는 코드를 함수로 묶거나 자주 등장하는 메소드들을 묶어 클래스로 만들어duplication을 없애고 class를 만들고 이름을 바꾼다.

 

Refactor 단계가 점점 커지면서 Design Pattern 등을 함

 

TDD 원칙: 요구 사항을 최소한으로 하기.

한 사이클에서의 테스트 양을 적게 해라. 예를 들어 함수 몇 개씩, 클래스 하나의 메소드 몇 개씩. 이것의 효과는 디버깅하기가 편리하다는 것(요구 사항이 적으므로 어디서 오류가 발생하는 지를 찾기가 편함), 별도의 문서가 없어도 테스트 코드를 통해 이해할 수 있다.

 

TDD in Python

원시적인 방법: shell을 이용하여 테스트하기, 예상되는 값을 이용해 테스트하기

Assert를 이용하여 테스트하기: 조건이 부합하면 통과하고 아니면 프로그램을 중단한다. (AssertionError)

Ex) assert p.cost == 183419.0

unittest 라이브러리를 사용한다. 이는 테스트를 자동화해주고 체계적인 테스트를 해주며 테스트 레포트가 있다. (Ran 2 tests in 0.002s OK.)

Test case: 테스트할 것을 테스트 케이스로 정리

Test Runner: 전체적인 소프트웨어 테스트를 수행함. 구체적인 항목들이 있는 suite를 실행

Test Suite: 어떤 테스트를 해야 할지에 대한Test case들을 가짐. 구체적인 항목을 집어넣음.

 

Python Unittest 과정

1.     Testcase를 베이스 클래스로 하는 테스트 클래스 생성

2.     테스트할 것들을 메소드로 만들어 나열

3.     각 메소드 내의 assertEqual가 에러를 확인. 에러가 나더라도 중단시키지 않고 끝까지 테스트한다.

C++: google test, cppUtest

 

unittest.Mock

다른 사람의 코드를 사용해 짠 코드를 테스트해야 하는데 아직 다른 사람이 코드를 다 짜지 않았을 때

Pair programing 중에 아직 팀원의 테스트 코드가 작성 중 일 때

팀플 중에 내가 일부만 담당했을 때

진짜 오브젝트의 동작을 모방한 것.

외관만 짜여진 것이다. 실체가 아닌 껍데기, prototype

 

Profiling (computer programming): 동적 프로그램 분석: 성능

Software을 분석하는 것이다. 어느 함수가 얼마나 시간을 썼고, 메모리를 얼만큼 썼는 지 등을 분석한다. 알고리즘을 최적화하는 데 도움을 준다. 비동기 및 병렬 처리에 도움을 준다. Profiler는 시간을 잡아먹는 애들을 처리하기도 한다.

Python에서 re, cProrfile 라이브러리를 통해 할 수 있다.

RunSnakeRun, SNAKEVIZ(Profiler Visualization Opensource for Python)

Profiling: 성능 얘기

 

Coding Guideline (or Convention): 가독성을 위해

권장하는 프로그래밍 스타일, 파일 이름, 디렉토리 경로, 중괄호를 어디에서 여는 지 등

가이드라인이 문서화되어 있다.