- 디버깅
- 테스트 주도 개발 (TDD) / 유닛테스트
- Chai / Mocha
- OR 연산자
- 매개변수와 인수
- 스코프
- Array 메소드
- 클로저
작은 기능 검사하기
사소한 함수를 제외 모든 함수에 유닛테스트를 거친다.
전문적으로 구축된 소프트웨어 시스템은 100 ~ 1000개의 유닛 테스트가 작동.
유닛테스트 구성요소
주장 (Assertions)
테스트를 구성할 때 콘솔로 유닛테스트를 하는 방식은 문제가 되지않는다. 그러나 전문적 프로그래머들은 Assertion을 기반으로 한 프레임워크를 사용하여 잘 구성된 테스트를 통해 발생한 문제를 빠르게 대처할 수 있어야 한다.
Matcher
expect(output).to.equal();
.to.equal() - Matcher에 해당되는 부분
Assertion과 Matcher가 같아야
class 를 포함하는 경우 class에 대한 예시 명시
테스트 환경을 따로 준비하거나 테스트 실행 후 초기화 코드 준비
유닛테스트 작성법
범주적 추론을 통해 작성하고자 하는 코드가 기능을 충실히 이행할 수 있도록 모든 범주를 마련해놔야 한다.
테스트할 코드는 절대 테스트를 진행하는 코드 안에 넣으면 안된다.
두 배열간의 비교는 값에 대한 비교가 아닌 주소에 대한 비교가 이뤄지기 때문에 이를 테스트하려면 배열 안의 값을 다 문자열로 만든 후 비교한다. ( JSON.stringify()
)
그러나 순서가 다를 경우의 문제가 존재한다
https://github.com/inspect-js/node-deep-equal/blob/master/index.js
mocha
모카를 사용하면 원하는 어설션 라이브러리를 사용할 수 있다 ex) chai.
자바스크립트 테스트 프레임 워크
describe('#indexOf()', function () {
it('should return -1 when the value is not present', function () {
[1, 2, 3].indexOf(5).should.equal(-1);
[1, 2, 3].indexOf(0).should.equal(-1);
});
});
describe('my suite', () => {
it('my test', () => {
// should set the assertion code
});
});
//HOOKS
describe('hooks', function () {
before(function () {
// runs once before the first test in this block
});
after(function () {
// runs once after the last test in this block
});
beforeEach(function () {
// runs before each test in this block
});
afterEach(function () {
// runs after each test in this block
});
// test cases
});
Chai
Chai is a BDD / TDD assertion library
Chai has several interfaces that allow the developer to choose the most comfortable.
Assert
//Assert
var assert = chai.assert;
var assert = require('chai').assert
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };
assert.typeOf(foo, 'string'); // without optional message
assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
assert.equal(foo, 'bar', 'foo equal `bar`');
assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');
expect / should
둘 중에 어느 것을 사용해도 되지만 스타일 변경해야 되고, 스타일 일관성이 중요하므로 둘 중 하나를 선택하여 작성한다. (http://chaijs.com/guide/styles)
/
/html
<script src="chai.js" type="text/javascript"></script>
//expect
let expect = chai.expect;
var expect = require('chai').expect
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };
expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
expect(foo).to.have.lengthOf(3);
expect(beverages).to.have.property('tea').with.lengthOf(3);
//should
let should = chai.should();
var should = require('chai').should() //actually call the function
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
beverages.should.have.property('tea').with.lengthOf(3)
@@ OR 연산자를 사용하다가 var num === 8 || 9
같은 요상한 식을 생각해냈다. 이건 왜 안되지? 하고 콘솔로 찍어보니. num 값이 8이면 true를 반환하고 8 이 아니면 숫자 9를 반환하더라. 9도 truthy
한 값이라 if 조건식에 넣으면 실행 구문이 돌아가긴 하겠지만 8이나 9일때 동작시키고 싶었던 터라 무용지물이 되어버렸다. OR 연산자나 AND 연산자 통해서 사용할 때 조금이라도 더 간략하게 쓸순 없을까 고민하다가 나온.... 이상한... 식. 간략하는 방법은 더 고민을 해봐야겠다. 끙..
let cardNum = '123143541512';
if((cardNum[0] === '1' || cardNum[0] === '2') && cardNum.length === 12 ){
console.log('카드 첫글자는 1이거나 2, 글자 갯수는 12개입니다.');
}
매개변수와 전달인자는 문맥에 따라 의미를 달리해서 해석된다.
매개변수 ( Parameter )
함수의 정의에서 전달받은 인수를 함수 내부로 전달하기 위해 사용하는 변수
기본 자료형인 매개변수는 값으로 함수에 전달된다. 즉 값이 함수로 전달된다.
함수가 매개변수의 값을 바꾸더라도 전역적으로 또는 함수를 호출하는 곳엔 반영되지 않으나,
매개변수로 배열이나 객체같이 기본 자료형이 아닌 참조형 자료의 속성을 변하게 하는 경우 그 변화는 외부에서도 볼 수 있다.
function myFunc(theObject) {
theObject.make = "Toyota";
}
var mycar = {make: "Honda", model: "Accord", year: 1998};
var x, y;
x = mycar.make; // x 의 값은 "Honda" 입니다.
myFunc(mycar);
y = mycar.make; // y 의 값은 "Toyota" 입니다.
// (make 속성은 myFunc에서 변경되었습니다.)
디폴트 매개변수와 나머지 매개변수 (ECMAScript2015)
디폴트 매개변수와 함께라면, 함수 본문에서 검사하는 부분은 필요가 없습니다. 이제 , 함수 머리에서 b 의 기본값에 간단히 1을 넣어주면 됩니다
function multiply(a, b = 1) {
return a*b;
}
multiply(5); // 5
나머지 매개변수
function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
인수 (arguments)
함수가 호출될 때 함수로 값을 전달해주는 값
arguments 객체는 함수가 호출 될 때 전달된 인수를 배열의 형태로 저장하고 있다.
함수의 인수는 배열과 비슷한 객체로 처리가 된다. 함수 내에서는 전달된 인수를 다음과 같이 다룰 수 있다. arguments[i]
function myConcat(separator) {
// arguments를 이용하여 반복한다
for (i = 1; i < arguments.length; i++) {
console.log(arguments[i])
console.log(separator);
}
}
myConcat(", ", "red", "orange", "blue");
//red VM574:4
//, VM574:5
//orange VM574:4
//, VM574:5
//blue VM574:4
//, VM574:5
자바스크립트는 함수의 정의보다 적은 수의 인수가 전달되더라도 오류가 발생하지 않는다.
전달되지 않은 매개변수에 자동으로 undefined 값이 설정돼있다.
[Array.method]
arr.reduce()
여러가지 배열을 단 하나의 값으로 만들어주는 메소드
단 하나의 값으로 줄인다.
array Method
arr.map()
[닭, 돼지, 감자] ⇒ [치킨,삼겹살,포테이토칩]
arr.filter()
[닭,돼지,옥수수] ⇒ [옥수수]
arr.reduce()
[오이, 밥, 고기] ===짬뽕=⇒ 비빔밥
[클로저]
클로저를 이용한 Private 선언
캡슐화 / 은닉화에 좋다
클로저는 외부함수 값에 접근을 무조건 해야 클로저는 아니다.
//팩토리 패턴
function makeCounter(){
let privateCounter = 0;
return {
increment : function (){
privateCounter++;
},
decrement : function(){
privateCounter--;
},
getValue: function(){
return prevateCounter;
}
}
}
let counter1 = makeCounter();
let counter2 = makeCounter();
//클래스
class Car {
constructor (name, color, brand){
this.name = name;
this.color = color;
this.brand = brand;
}
drive(){
console.log('부릉' + this.name );
}
}
@@ 오늘은 테스트 빌더 과제를 진행하면서 테스트 주도 개발, 유닛테스트에 대해 익혔다. 새로운 페어분과 Chai, Mocha 기반 테스트 파일을 작성하며, 과제를 테스트 하기 위해 고군분투 페어 프로그래밍을 진행했다.
많이 헤매고, 또 뭔가 처음 보는 코드들이라서 긴가민가 헷갈리기만 했는데 그래도 생각보다 일찍 코드 작성을 마쳤다. 내일까지인 페어 스케줄이 오늘 다 끝나버려서 처음부터 다시 진행해보기로 했다.
코드를 새롭게 작성하는 것보다 깔끔하게 수정하고 고치는 것이 더 어렵다는 것을 실감한 하루다.
클로저 개념을 또 잘 못 알고 있었다. 참 클로저는 알다가도 모를 녀석... 정규학습 시간 마치고 저녁에 진행한 AMA를 들을까 말까 고민하다가 들었는데 꽤나 유익한 시간이었다. 미리 앞으로 나갈 학습에 대해서 귀띔을 받는 기분이었다. 완전하게 다 파악할 수는 없더라도 한번이라도 들어본 것에 대한 학습이 더 빠르다는 것을 아니까 앞으로도 꾸준히 들어야겠다.
잘봤습니다. 내용이 좋네요. 감사합니다~!