[JavaScript] 자바스크립트에서의 Test Suite[JavaScript] 자바스크립트에서의 Test Suite

Posted at 2018. 12. 25. 17:15 | Posted in JavaScript & jQuery/JavaScript
반응형




■ 테스트 스위트란?



테스트 스위트의 주된 목적은 개별 테스트를 묶어 하나의  자원으로 제공함으로써

여러 테스트를 한 번에 실행할 수 있게 그리고 반복해서 간단히 실행할 수 있게 하는 것이다.




#01. 검증 조건


단위 테스트 프레임워크의 핵심은 검증 메서드로, 이 메서드의 이름은 일반적으로 assert( ) 이다.

해당 메서드는 항상 검증의 전제가  되는 표현 하나와 검증의 목적을 설명하는 인자를 받는다.

해당 표현 값이 ""이거나 "참 이 될 수 있는 값"이면 검증 조건을 통과하게 된다.

그렇지 않으면, 실패로 간주된다.

연관된 문구는 보통 성공 / 실패 표시와 함께 출력된다.

다음 코드에서 이 개념의 간단한 구현을 볼 수 있다.



# 소스 코드

 test_suite.php

<html>
  <head>
    <title>:: 테스트 스위트 ::</title>
    <script type="text/javascript">

      // assert() 메서드 정의
      function assert(value, desc) {
        var li = document.createElement("li");
        li.className = value ? "pass" : "fail";
        li.appendChild(document.createTextNode(desc));
        document.getElementById("results").appendChild(li);
      } // END function assert(value, desc)

      // 검증 조건을 이용해서 테스트 실행
      window.onload = function() {


        assert(true, "테스트 스위트 러닝");
        assert(false, "테스트 실패");
      } // END window.onload = function()
    </script>
    <style type="text/css">
      /* 결과를 출력할때 구분할 스타일 정의 */
      #results li.pass { color:#008000; }
      #results li.fail { color:#FF0000; }
    </style>
  </head>
  <body>
    <!-- 테스트 결과 수집 -->
    <ul id="results"></ul>
  </body>
</html>




# 출력 결과






#02. 테스트 그룹



간단한 검증 조건만으로도 유용하지만, 테스트 내용에 따라서 테스트를 그룹으로 묶을 때, 이는 정말로 유용해지기 시작한다.


단위 테스트에서, 하나의 테스트 그룹은 API나 애플리케이션에서 주로 어떤 한 메서드와 연관된 검증 조건들의 집합을 나타낸다.


또한 행위 주도 개발(behavior-driven development)을 한다면, 테스트 그룹은 태스크에 대한 검증 조건의 집합이 될 것이다.


어쨌거나 두 경우 모두, 테스트 그룹을 구현하는 방식은 거의 동일하다.



다음 테스트 스위트 예제는 테스트 그룹을 제공하고, 테스트 그룹 내에 포함된 각 검증 조건에 대한 결과는 results에 저장된다.


게다가 어떤 검증 조건이 하나라도 실패하면, 전체 테스크 그룹은 실패로 표시된다. 다음 코드의 결과는 꽤 간단하지만,


몇 단계의 동적 제어(테스트 그룹 내에 실패한 테스트가 있을경우, 테스트 그룹을 확장 / 축소하거나 필터링 하는것)는


실제로 매우 유용할 것이다.




# 소스 코드

 group_test_suite.php

<html>
  <head>
    <title>:: 테스트 그룹 구현 ::</title>
    <script type="text/javascript">

      // 익명 즉시 실행 함수 정의
      (function() {
        var results = "";
        this.assert = function assert(value, desc) {
          var li = document.createElement("li");
          li.className = value ? "pass" : "fail";
          li.appendChild(document.createTextNode(desc));
          results.appendChild(li);

          if(!value) {
            li.parentNode.parentNode.className = "fail";
          }

          return li;
        };

        this.test = function test(name, fn) {
          results = document.getElementById("results");
          results = assert(true, name).appendChild(document.createElement("ul"));
          fn();
        };
      })(); // (function())

      // 검증 조건을 이용해서 테스트 실행
      window.onload = function() {
        test("A test.", function() {
          assert(true, "첫번째 증명 성공");
          assert(true, "두번째 증명 성공");
          assert(true, "세번째 증명 성공");
        });

        test("B test.", function() {
          assert(true, "첫번쨰 테스트 성공");
          assert(false, "두번쨰 테스트 실패");
          assert(true, "세번쨰 테스트 성공");
        });

        test("C test.", function() {
          assert(null, "fail");
          assert(5, "pass");
        });
      } // END window.onload = function()
    </script>
    <style type="text/css">

      /* 결과를 출력할때 구분할 스타일 정의 */
      #results li.pass { color:#008000; }
      #results li.fail { color:#FF0000; }
    </style>
  </head>
  <body>
    <!-- 테스트 결과 수집 -->
    <ul id="results"></ul>
  </body>
</html>




# 출력 결과



위코드는 먼저 테스트한 test_suite.php 페이지의 assert( ) 함수의 로깅 구현과 크게 다르지 않다.


가장 큰 차이는 현재 테스트 그룹을 참조하는(검증 조건을 적절히 로깅하기 위한 수단인) results 변수를 포함하고 있느냐이다.


비동기 테스트 동작을 다루는 방식 역시 테스트 프레임워크의 중요한 측명가운데 하나다.







#03. 비동기 테스트



많은 개발자들이 자바스크립트 테스트 스위트 개발 중에 만나는 힘들고 복잡한 작업은 비동기 테스트다.


Ajax 요청이나 애니메이션처럼, 비동기 테스트는 예측할 수 없는 시간이 지난 후에야 결과를 받게 될 것이다.


비동기 테스트의 이러한 이슈를 다루는 작업은 오버엔지니어링이 되기 쉽상이고, 필요 이상으로 일을 복잡하게 만들기도 한다.


비동기 테스트를 다루려면 다음 단계를 따라야 한다.



    ① 동일한 비동기 연산에서 사용해야 한는 검증 조건은 같은 테스트 그룹으로 묶어야 한다.


    ② 각 테스트 그룹은 하나의 큐에 존재해야 하고, 이전 테스트 그룹이 모두 종료한 뒤에 실행되어야 한다.




이렇게, 각 테스트 그룹은 비 동기적으로 실행될 수 있다.




# 소스 코드

 asynchronous_test_suite.php

<html>
  <head>
    <title>:: 비동기 테스트 스위트 ::</title>
    <script type="text/javascript">

      // 익명 즉시 실행 함수 정의
      (function() {

        var queue = [];
        var paused = false, results;

        this.test = function(name, fn) {

          queue.push(function() {
            results = document.getElementById("results");
            results = assert(true, name).appendChild(document.createElement("ul"));
            fn();
          });

          runTest();
        };

        this.pause = function() {

          paused = true;
        }

        this.resume = function() {

          paused = false;
          setTimeout(runTest, 1);
        }

        function runTest() {

          if(!paused && queue.length) {
            queue.shift()();
            if(!paused) {
              resume();
            }
          }
        }

        this.assert = function assert(value, desc) {

          var li = document.createElement("li");
          li.className = value ? "pass" : "fail";
          li.appendChild(document.createTextNode(desc));
          results.appendChild(li);

          if(!value) {
            li.parentNode.parentNode.className = "fail";
          }

          return li;
        };
      })(); // END (function())

      // 검증 조건을 이용해서 테스트 실행
      window.onload = function() {

        test("비동기 테스트 #01.", function() {
          pause();
          setTimeout(function() {
            assert(true, "첫번째 테스트 성공");
            resume();
          }, 1000);
        });

        test("비동기 테스트 #02.", function() {
          pause();
          setTimeout(function() {
            assert(false, "두번째 테스트 실패");
            resume();
          }, 1000);

          test("비동기 테스트 #03.", function() {
            pause();
            setTimeout(function() {
              assert(true, "세번째 테스트 성공");
              resume();
            }, 1000);
          });
        });
      } // END window.onload = function()
    </script>
    <style type="text/css">

      /* 결과를 출력할때 구분할 스타일 정의 */
      #results li.pass { color:#008000; }
      #results li.fail { color:#FF0000; }
    </style>
  </head>
  <body>
    <!-- 테스트 결과 수집 -->
    <ul id="results"></ul>
  </body>
</html>





# 출력 결과




asynchronous_test_suite.php 페이지에는 외부에서 사용 가능한 test( ), pause( ), resume( ) 함수가 세 개가 있다.


이 세 함수는 다음 특성을 따른다.




    ① test( fn )


        -. 다수의 검증 조건을 가지고 있는 함수를 인자로 받고, 이 함수를 테스트 실행을 위한 큐에 저장한다.

        -. 함수가 가지고 있는 검증 조건은 동기나 비동기로 실행될 것이다.



    ② pause( )


        -. test( ) 함수 안에서 실행된다.

        -. 현재 테스트 그룹의 실행이 완료될 때까지, 테스트 스위트에 실행 중인 전체  테스트를 정지하라고 알려준다.



    ③ resume( )


        -. test( ) 함수를 재개하고, 이전 코드가 오래 실행되어 전체 코드가 멈추는 것을 방지하기 위해서

          잠시 동안의 딜레이를 준 다음 테스트를 실행한다.





내부적인 구현 함수는 runTest( ) 이며 테스트가 큐에 저장되거나 빠질 때 호출된다.


테스트 스위트가 현재 정지되지 않았는지를 체크하고, 큐 안에 테스트가 있다면, 테스트를 큐에서 빼서 실행을 시도한다.


게다가 테스트 그룹의 실행이 종료된 후에, runTest( )는 테스트 스위트가 현재 정지되어 있는지를 검사하고,


그렇지 않다면(테스트 그룹 안에 비동기 테스트만 실행된고 있다면),


runTest( )는 다음 테스트 그룹을 실행하기 시작한다.





반응형
//

[JavaScript] Password 형식 검사하기[JavaScript] Password 형식 검사하기

Posted at 2018. 10. 24. 15:08 | Posted in JavaScript & jQuery/JavaScript
반응형




패스워드 형식 검사하기




# 소스코드

<html>
<head>
<title>:: JAVASCRIPT 비밀번호 검사 ::</title>
<script type="text/javascript">
    function checkPasswordPattern(str) {

        var pass = str.value;
        var message = "";

        // 비밀번호 문자열에 숫자 존재 여부 검사
        var pattern1 = /[0-9]/;  // 숫자
        if(pattern1.test(pass) == false) {
            message = "비밀번호에 숫자가 입력되지 않았습니다.\n숫자를 입력하여 주시기 바랍니다.";
        }

        // 비밀번호 문자열에 영문 소문자 존재 여부 검사
        var pattern2 = /[a-z]/;
        if(pattern2.test(pass) == false) {
            message = "비밀번호에 영문 소문자가 입력되지 않았습니다.\n영문 소문자를 입력하여 주시기 바랍니다.";
        }

        // 비밀번호 문자열에 영문 대문자 존재 여부 검사
        var pattern3 = /[A-Z]/;
        if(pattern3.test(pass) == false) {
            message = "비밀번호에 영문 대문자가 입력되지 않았습니다.\n영문 대문자를 입력하여 주시기 바랍니다.";
        }

        // 비밀번호 문자열에 특수문자 존재 여부 검사
        var pattern4 = /[~!@#$%^&*()_+|<>?:{}]/;  // 특수문자
        if(pattern4.test(pass) == false) {
            message = "비밀번호에 특수문자가 입력되지 않았습니다.\n특수문자를 입력하여 주시기 바랍니다.";
        }

        // 비밀번호 문자열의 입력 길이 검사
        if(pass.length < 8 || pass.length > 16) {
            message = "비밀번호는 8자리 이상 16자리 이하만 가능합니다.\n비밀번호를 다시 입력하여 주시기 바랍니다.";
        }

        // 비밀번호 문자열 결과 출력
        if(message) {
            alert(message);
            str.value = "";
            str.focus();
            return false;
        } else {
            alert("사용하셔도 좋은 비밀번호 입니다.");
        }
    }
</script>
</head>
<body>
    <!-- input type="password" id="" value=""/ -->

    <!-- 스타일 ime-mode:disabled 속성은 textbox에 영문만을 입력되게 한다. -->

    <input type="text" id="memberPw" value="" style="ime-mode:disabled;"/>

    <input type="button" onClick="checkPasswordPattern(memberPw);" value="검사"/>
</body>
</html>





# 출력결과










■ 패스워드 형식 실시간 검사하기




위에서 패스워드 형식을 검사하는 자바스크립트 함수를 만들어 보았다.


그렇지만 위 방법은 사용자가 작성하고 버튼을 다시 클릭하고


비밀번호 형식에 적합하지 않으면은 다시 입력하고 또 클릭하는 불필요한 작업이 많기에.


실시간으로 비밀번호의 형식을 검사해 보려고 한다.




# 소스코드

<html>
<head>
<title>:: JAVASCRIPT 비밀번호 안전성 겁사 ::</title>
<script type="text/javascript">
    function safetyPasswordPattern(str) {

        var pass = str.value;
        var message = "";
        var color = "";
        var checkPoint = 0;

        // 입력값이 있을경우에만 실행
        if(pass.length) {

            // 최대 입력 글자수를 제한한다.
            if(pass.length < 8 || pass.length > 16) {
                message = ":: 최소 8자 이상, 최대 16자 이하 ::";
                color = "#A23E48";
            }

            // 문자열의 길이가 8 ~ 16 인경우
            else {

                // 비밀번호 문자열에 숫자 존재 여부 검사
                var pattern1 = /[0-9]/;  // 숫자
                if(pattern1.test(pass) == false) {
                    checkPoint = checkPoint + 1;
                }

                // 비밀번호 문자열에 영문 소문자 존재 여부 검사
                var pattern2 = /[a-z]/;
                if(pattern2.test(pass) == false) {
                    checkPoint = checkPoint + 1;
                }

                // 비밀번호 문자열에 영문 대문자 존재 여부 검사
                var pattern3 = /[A-Z]/;
                if(pattern3.test(pass) == false) {
                    checkPoint = checkPoint + 1;
                }

                // 비밀번호 문자열에 특수문자 존재 여부 검사
                var pattern4 = /[~!@#$%^&*()_+|<>?:{}]/;  // 특수문자
                if(pattern4.test(pass) == false) {
                    checkPoint = checkPoint + 1;
                }

                if(checkPoint >= 3) {
                    message = ":: 보안성이 취약한 비밀번호 ::";
                    color = "#A23E48";
                } else if(checkPoint == 2) {
                    message = ":: 보안성이 낮은 비밀번호 ::";
                    color = "#FF8C42";
                } else if(checkPoint == 1) {
                    message = ":: 보안성이 보통인 비밀번호 ::";
                    color = "#FF8C42";
                } else {
                    message = ":: 보안성이 강력한 비밀번호 ::";
                    color = "#0000CD";
                }
            }
        }

        else {
            message = ":: 비밀번호를 입력해 주세요 ::";
            color = "#000000";
        }

        document.getElementById("makyText").innerHTML = message;
        document.getElementById("makyText").style.color = color;
    }
</script>
</head>
<body>

    <!-- 스타일 ime-mode:disabled 속성은 textbox에 영문만을 입력되게 한다. -->

    <input type="text" id="memberPw" value="" onKeyup="safetyPasswordPattern(this);" style="ime-mode:disabled;"/>
    <br/>
    <span id="makyText">:: 비밀번호를 입력해 주세요 ::</span>
</body>
</html>




# 출력결과





반응형
//

[JavaScript] 읽기 쉽고, 유지보수하기 쉬운 코드 작성하기 - 코딩규약[JavaScript] 읽기 쉽고, 유지보수하기 쉬운 코드 작성하기 - 코딩규약

Posted at 2018. 10. 12. 12:01 | Posted in JavaScript & jQuery/JavaScript
반응형




■ 깔끔한 코드, 작성하고 있는가?




 AJAX가 보금되에 따라 JavaScript에서도 비교적 대규모의 코드를 작성할 기회가 많아졌다. 그에 따라서 프로그램을 단 한번만 작성해서 「자, 이걸로 마지막!」 이라고 하는 일은 점차 없어지게 되었다. 애플리케이션을 운용해 나가는 상황에서 버그가 발견되면 수정하거나 나중에 발생한 요구 안건에 따라 코드를 추가 / 갱신하는 등 프로그램은 항상 변경될 가능성에 노출되어 있다.

 그리고 프로그램을 변경하는 경우에 우선적으로 필요로 하는 것은 「코드를 읽어 이해하는」 분석 작업이다. 이 「읽고 이해하는」이라고 하는 작업은 때로는 「작성하기」보다 큰 이인경우도 있다. 자신이 작성한 코드라 해도 시간이 지난 후에 읽어보게 되면 의외로 뭐가 뭔지 알지 못하는 경우가 많은데, 그것이 타인의 코드라면 더 말할 것도 없다. 그러므로 일상적으로 발생할 수 있는 변경을 생각하면 깔끔한(=읽기 쉬운) 코드를 기술하는것이 중요하다.

 깔끔한 코드라는 것이 어떤 건지 이미지가 좀처럼 떠오르지 않을 수도 있다. 그런 사람은 코딩 규약이라는 것을 추천한다. 코딩 규약이란, 이른바 변수의 명명규칙에서부터 스페이스나 인덴트 넣는 방법, 코멘트 쓰는 법 등 통일성을 취한 코드를 기술하는 데 필요한 룰을 정하는 것이다. 규약에 따라 코드를 기술함으로써 최소한 「더럽지 않은」 코드를 기술할 수 있게 된다.

JavaScript에서도 이러한 코딩 규약이 Mozilla Developer Center 에서 JavaScript Style Guide 로 공개되어 있다.

여기에 정해져 있는 규약이 전부는 아니지만, 한번 훑어보면 좋은 공부가 될 것이다.

다음은 JavaScript Style Guide 에서 제시하고 있는 주요 포인트들이다(어디까지나 규약이며, 구문 규칙이 아닌 점에 주의하길 바란다).


#01. 기본


 -. 1행당 자릿수는 80문자 이하로 할것
 -. 파일의 말미는 개행할 것
 -. 함수나 객체 등의 정의 블록의 전후는 공백 행으로 단락지을것
 -. 문자 코드 세트는 UTF-8



#02. 공백


 -. 인스턴트는 스페이스 2개로 표현할 것(탭은 사용하지 않는다.)
 -. 2항 연산자는 공백으로 단락지을것
 -. 콤마 / 세미콜론, 키워드의 후방에는 공백을 포함할것(다만, 줄 끝의 공백은 불필요)



#03. 명명규칙


 -. 변수, 함수명은 선두 소문자의 camelCase 형식
 -. 정수명은 모두 대문자의 언더스코어 형식
 -. 생성자(객체)명은 선두 대문자의 CamelCase 형식
 -. 프라이비트 멤버는 「 _ 」로 시작할것
 -. 이벤트 핸들러 함수는 [on]으로 시작할것



#04. 그 외


 -. 모든 변수는 선언, 초기화할 것
 -. 변수의 선언이 중복되지 않을 것
 -. 배열, 객체의 생성에는 […], {…} 등의 리터럴 구문을 이용할것
 -. 논리값 true / false와 비교하지 않을것



■ Google 표준의 코딩 스타일




또한 Google이 제공하고 있는 Google JavaScript Style Guide 도 있다. 앞의 것과 중복하지 않는 범위에서 중요한 것을 정리해 두었다.

 · .js 파일의 이름은 소문자로 통일
 · 세미콜론은 생략하지 않는다.
 · 문자열의 괄호에는 「"」쌍 따옴표 보다 「'」홑 따옴표를 우선해 이용한다.
 · 기본 데이터형(String)이나 number, boolean등)이 랩퍼 객체는 사용하지 않는다.
 · 네임스페이스를 이용하고, 글로벌 레벨의 이름은 최소한으로 억제한다.
 · 블록을 나타내는 {...}의 전에 개행은 너지 않는다.
 · eval 함수는 deserialize에서만 이용한다.
 · 빌트인 객체의 프로토타입은 고쳐 써선 안 된다.
 · with 명령은 이용하지 않는다.
 · for...in 명령은 연관배열 / 해시에서만 이용한다.



여기서 나타나고 있는 가이드 라인은 코드를 일기 쉽게 하기만 할 뿐만 아니라 안전한 코드를 기술한다는 의미에서도 중요하다.



반응형
//

[JavaScript] email 형식 검사하기[JavaScript] email 형식 검사하기

Posted at 2018. 9. 27. 18:30 | Posted in JavaScript & jQuery/JavaScript
반응형




■ email 형식 검사하기




# 소스코드

<html>
<head>
<title>:: JAVASCRIPT e-Mail 형식 검사 ::</title>
<script type="text/javascript">
    function inputeIsEmail(mail) {
       
        // 변수를 선언한다.
        var regExp = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

        // 이메일 확인
        // test( ) : 검색한 문자열에 패턴이 있는지 여부를 나타낸다, 문자열이 존재하면 true, 존재하지 않으면 false를 리턴한다.
        if(regExp.test(mail.value) == false) {
            alert("e-mail 형식이 일치하지 않습니다.\n다시 입력하여 주시기 바랍니다.");
            mail.value = "";
            mail.focus();
        } else {
            alert("e-mail 형식에 맞게 입력하였습니다.");
        }
    }
</script>
</head>
<body>
    <input type="email" id="mail" value=""/>
    <input type="button" onClick="inputeIsEmail(mail);" value="검사"/>
</body>
</html>




# 출력결과




반응형
//