업무 중에 자료 구조를 쓸일이 있을까? 라는 생각을 QA 활동을 하다보니 하게되었고


따로 혼자서 공부를 하려다보니까 그것도 잘되지 않더군요 ( 그시간에 html css, js 를 !)


이라고 하였으나


머릿속엔 일하면서 어떻게 하면??


어떻게 하면 자동화 하는 구조를 좀더 이쁘게 할수 있을까는 고민했습니다.


어느정도 자동화 프로세스는 갖추어졌는데 중앙 관리자 (Redux에서는 Store라고 표현하던데)


의 상태관리를 어떻게 하면 좋을까 라는 생각을 매번하다가 나온 구조가 


var obj = {
   "widget":{
      "api":{
         "setFocus":{
            "contents":"setFocus 입니다.",
            "tc":"WIDGET_API_SETFOCUS",
            "result":"fail"
            }
        },
      "attr":{
         "page-length":{
            "contents":"page-length 확인 ",
            "tc":"WIDGET_ATTR_PAGE_LENGTH",
"result":"fail" }, "length-change":{ "contents":"length-change 확인", "tc":"WIDGET_ATTR_LENGTH_CHANGE", "result":"fail" } }, "event":{ "onclick":{ "callback":{ "contents":"onclick 콜백 테스트 ", "tc":"WIDGET_ONCLICK_CALLBACK", "result":"fail" }, "event":{ "contents":"wiget_event 파라미터 테스트", "tc":"WIDGET_ROWCLICK_EVENT_PARAM", "result":"block" }, "widget":{ "contents":"내용222", "tc":"WIDGET_ONCLICK_WIDGET_PARAM", "result":"block" } }, "ondblclick":{ "callback":{ "contents":"내용333333", "tc":"TC", "result":"나온다" }, "event":{ "contents":"내용333333", "tc":"TC", "result":"나온다" }, "widget":{ "contents":"내용222", "tc":"TC", "result":"나온다" } }, } }, "widget2":{ "api":{} } }


와 같은 구조로 나왔습니다. 필요한 케이스는 맨 마지막 leaf에 존재하게 되는데


해당 길이를 잡고 Iterator를 하게되면  TC(TestCase) , TS(Test Suite) 가 추가 됐을때 그에 따른 순환하는 로직을 다시 


수정해주어야 하는 불상사가 발생하게 됩니다.


해당 의 구조를 그림으로 그려보게 된다면






다른 부분들은 생략 하고 위와같은 그림의 형태가 되는 것으로 보입니다.


1. 전체 테스트 케이스 


제가 필요한 Object (contents와 tc , result)  내용과 정형화된 TC(TestCase) , 결과 를 가지고있는 객체를 반환하여야 합니다.


위젯의 종류는 70개가 넘고 그에 따른 속성은 30여개 이벤트는 20개  정도가 됩니다.


그럼 위와같은 형태의 obj 의 수가 엄청나게 나올게 될것으로 보이는데


일단 순회하기 위해서는 tree구조에서 level-순회 의 형태가 되어야 합니다.


자료구조 - 이진트리 레벨순회 관련 포스팅 

https://m.blog.naver.com/PostView.nhn?blogId=4717010&logNo=60210351999&proxyReferer=https%3A%2F%2Fwww.google.com%2F


레벨순회의 특징이라 함은 트리 순회시에 현재  레벨에 있는 Root노드를


Queue 에 넣어 놓고 꺼내서 자식노드를 순서대로 순회하는 형태입니다. 


해당의 순회 방법으로 leaf노드를 가져오게된다면 전체 테스트케이스를 가져올수 있습니다. 해당 내용은 따로 포스팅


2. 필요한 테스트 케이스 


특정 위젯의 특정 속성 특정 내용


button 위젯의 icon 속성 에 대한 내용


Repo.button.attr.icon 와 같은 형태로 접근이 가능하기 때문에 위의 구조는 현재 제가 생각 하기에 최적의 구조라고 


생각이 됩니다. 전체 순회만 level - 순회로 해결을 하면 ( 사이드 이슈없이 )


특정 케이스를 가져오는 방법은 JavaScript의 Object 접근자를 통해서 그대로 접근하여 값을 가져올수 있기 때문에


문제가 될것이 전혀 없어 보이며 다른 QA가 해당 케이스를 추가 한다고 하게된다면 


순회는 재귀 형태로 되면 문제가 되지 않을 거라 생각 되며 접근자 형태는 문제 될점이 없어 보입니다.


후 같이 의논할수 있는 분이 있으면 참 좋겠지만 ㅜㅜ 아직은 없군용..


ETC


현재 구조를 짜는 형태를 가지고있는데 구조가 완료되면 Prototype이든 모듈패턴이든  모듈형태로 만들어서 사용할 


예정입니다. 단순히 걱정되는건 해당 Repo를 setter , getter를 통해서 제어를 하게 될텐데


퍼포먼스 문제가 있냐 없냐 입니다. 실제 서비스는 아니지만 그래도 적응 양은 아니며 자동화를 진행하게된다면 


웹드라이버가 진행하면서 setter , getter가 이 속도를 따라 올수 있냐의 유무를 실제 적용해보지 않고서는 


확증이 서진 않는 상황이지만 일단은 자동화 구조가 있어야 도니.. 일단은 해당 구조로 진행 해야겠네용













안녕하세요 VanillaJS를 통해서 특정 작업을 하기전에 페이지 관련 내용들을 작성하여야 합니다.


(포스팅이 조금 늦은감이 있지만 ㅜ 주말까지 일을 하다보니.... )


index.html 이죠!!  제작되고있는 


전체 코드는  아래에 있습니다. (github) 에 올려놓고 있죠 후훗 


reactStudy/myVaniilaJS 에 있습니다.


VanillaJS 개요


https://ipex.tistory.com/224


그래서 오늘은 페이지의 메인이 되는 


index.html 을 작성하려고 합니다.


index.html


우선 해당 메인 페이지 의 작성은 프론트엔드 체크리스트 라는 사이트를 통해서 작성 하였습니다.


해당은 선언문입니다.


<!doctype html>

자칫 태그로 잘못 아실수 있지만 태그는 아니고 해당 HTML 이 몇 버전으로 작성되었다! 라고 브라우저가 알수 있도록 선언해주는 선언문 입니다.  doctype은 문서의 가장 첫번째 에 오게 됩니다.


MDN 에서는 doctype을 이와같이 설명합니다.


" HTML 에서 문서 타입은  '필수' 이며 **preamble 이다.해당 선언은 브라우저가 렌더링시 **"쿼크 모드(quirks mode)" 로 전환하는 것을 방지한다.  즉 <!DOCTYPE html> 은 일부 사양과 호환되지 않는 다른 렌더링 모드를 사용하는 대신 브라우저가 관련 사양을 따르는데 최선을 다한다."


또한 브라우저에서는 doctype을 확인할수 있도록 API 로 지원 하고있습니다.


doctype = document.doctype;
  • doctype is a read-only property.

[IE 11 에서의 document.doctype]

[Chrome 에서의 document.doctype]




doctype에 따라서 html 버전을 다르게 갈수있습니다. doctype에 대해서는 

해당 블로그에 설명이 너무 잘되어있어 링크로 대체 하도록 하겠습니다~

http://aboooks.tistory.com/40


HTML 버전 종류 



HTML 2.0 (RFC1866 규격) - 1995년 11월 24일 

HTML 3.2 (W3C 권고안)   - 1997년 1월

HTML 4.0  (W3C 권고안)  - 1997년 12월

HTML 4.0  (W3C 권고안)  - 1998년 4월

HTML 4.01 (W3C 권고안)  - 1999년 12월


XHTML 1.0 (W3C 권고안)  - 2000년 1월 26일

XHTML 1.1 (W3C 권고안)  - 2000년 1월 26일

XHTML 2.0 (W3C 권고안)  - 2000년 1월 26일 (사라짐)


HTML 5   - 2012 발표

HTML 5   - 2014년 10월 28일 표준안 확정

HTML 5.1 - 2016년 11월 01일 표준안 확정

HTML 5.2 - 2017년 12월 14일 표준안 확정

HTML 5.3 - 현재 진행 중


현재 모두는 HTML5로 해야되다보니 HTML5는 따로 조사해보시면 될 것 같습니다!


**preamble

preamble (프리앰블) : 비트 동기 또는 프레임 동기 등을 위하여 프레임 단위에서 각 프레임의 맨 앞에  붙이는 영역 (HTML에선 어떤식의 렌더링이 될지 알려주고 약속 하는 작업을 뜻하는 것으로 보입니다.)



 **"쿼크 모드(quirks mode)" 



<!DOCTYPE html>을 선언하는 이유 중 브라우저가 쿼크모드가 되지 않기 위해서라고 되어있는데요 

quirks mode (비표준 모드) : 


우선 왜 있을 까 ?? 라는 생각부터 하게 되었는데요 현재의 브라우저(HTML5)에서는 W3C 웹표준을 많이 따르기 위해 많은 브라우저들이 노력하고 있습니다. 그렇기 때문에 HTML5을 기준으로 돌아갈수 있도록 doctype을 지원하고 개발자들 역시 그에 맞게 화면을 구성하고있는데


"오래된 페이지" 와의 호환성을 제공하기 위해 모든 브라우저는 이 "quirks Mode"를 지원하게 됩니다. 

(이또한 IE에서 많이 발생합니다. 이슈가)


현재라면 HTML5와 CSS3을 기준으로  계속 작성해 나가시면 될 것 으로 보입니다.


참고 하였던 사이트 ( 정말 유용 했습니다. )


1. Front-End-Checklist 

프론트엔드 개발자들이 가져야할 체크리스트를 해주는 사이트입니다.

정말 유용해서 두번 놀랐네요 (아직 모르는게 많다는 것도 깨닫게 해줬습니다.)


2. Free favicon web Site

파비콘을 무료로 제공하는 사이트입니다 (유료도 구매가 가능합니다.)

https://www.iconfinder.com/icon-sets/featured/free/5


3. favicon Convert Web Site 

2번에서 제공된 파비콘을 파비콘 아이콘으로 변경해주는 사이트입니다.

https://converticon.com/


> 설정은 16 x 16 에서 256 x 256 까지 전부 체크하시고  Save As 하시면 됩니다.




이제 index.html 의 !doctype html  선언이 끝났습니다.



■ html 태그 속성 지정 ( lang , dir )



<!-- 페이지 내의 언어 속성 부여 -->
<!-- 페이지 내의 글자 방향 속성 부여 -->
<!-- rtl : right to left-->
<html lang="ko" dir="ltr">


rtl  ltr 인데요 페이지 내에서의  글자 방향 속성 부여인데요 


접속자가 다른 지역 일 경우 글자 방향이 다르게 나타날수 있기 때문에 이에 대한 명시를 html 태그에 직접 해주셔야 합니다.!




■ meta 태그 



Describe metadata within an HTML document


HTML 문서 내의 메타 데이터를 설명 한다 라고 W3School 에는 명시되어있습니다. 


맞습니다. 제가 작성한 페이지 (HTML DOM) 에 있는 메타데이터를 설명하기 위한 태그입니다.


charset = 'utf-8'


<!-- 문자집합 선언 -->
<meta charset="utf-8"/>


제가 사용하는 페이지의 문자 집합은 utf-8 으로 지정합니다.


http-equiv , content 


<!-- Internet Explorer에게 최신의 렌더링 엔진을 사용 지시 -->
<meta http-equiv="x-ua-compatible" content="ie=edge"/>


IE 8 브라우저 부터 나타났던 호환성 보기에 대한 내용인데요  IE브라우저가 최신의 렌더링을 사용할수 있도록 지시합니다.


http-equiv의 경우 : HTTP 헤더의 이름을 값으로 가질수 있으며  같이 가질수 있는 content의 종류는


"content-security-policy"  ,"content-type" , "refresh", "set-cookie" 등이 있습니다. 자세한 사항은 MDN 참조


MDN : https://developer.mozilla.org/ko/docs/Web/HTML/Element/meta


name 


<!-- Meta Description -->
<meta name="author" content="jaeuk_lee"/>
<meta name="description" content="깍돌이 스터디 페이지입니다."/>
<meta name="front-end-study" content="front-QA "/>


문서 레벨의 메타데이터의 이름을 정의 하는 속성이 있습니다. 해당 속성은 content 에 담긴 값과 연관이 지어집니다.


author  : 해당 문서의 작성자 


description : 페이지의 내용에 대한 짧고 정확한 요약을 담음 (FireFox나 오페라 의 경우 이를 즐겨찾기 페이지의 기본 설명으로 사용)


application-name : 웹 페이지 내에서 실행될 어플리케이션의 이름을 지정합니다. 


generator  : 페이지를 생성한 소프트웨어의 식별자


keyword : 콤마(',') 로 구분된 페이지의 내용과 관련된 단어를 담음


referrer : 문서에서 전송된 요청에 첨부된 HTTP 헤더의 참조를 제어 ( 해당 내용은 MDN 참조 )


** 해당 내용중 name="referrer"의 경우 document.wirte 또는 appendChild로 동적 삽입시 참조자의  작동을 예측 불가능 (no-referer 적용)


// 메타 데이터를 담는 다른 요소들도 있습니다.

** base head link style title 


css 로딩 (JS보다 항상 우선적으로 로딩이 될수 있도록 합니다.)


<!-- css는 무조건 js보다 먼저 로딩이 되어야 한다. -->
<link rel="stylesheet" type="text/css" href="./lib/css/normalize.css"/>
<link rel="stylesheet" type="text/css" href="./lib/css/index.css"/>


CSS 는 JS보다 먼저 로딩 되어야 한다 !!


해당 문구를 보고 아 그냥 CSS가 JS보다 먼저 로딩이 되어야 한다 라는 생각을 가지고 쓰는거보다


왜? CSS가 JS보다 먼저 로딩이 되어야 하는가에 대해 알고 작성하게되면


페이지를 작성하게 되었을 때 여러 가지 도움이 됩니다. ( 성능 적인 이슈 등 등 )


이거에 대해 도움이 되었던 페이지를 링크 합니다.


// Naver D2 브라우저는 어떻게 동작 하는가?

https://d2.naver.com/helloworld/59361


가장 무난한 WebKit 브라우저에 동작 과정을 보자면 








HTML 파서를 통해서 HTML 을 파싱 후 -> DOM 트리 


CSS파서를 통해 CSS을 파싱 후 -> CSS 규칙을 생성 


두 작업이 끝나야 렌더트리를 구축하고 화면을 그리기 시작 하게됩니다.


하지만 해당 도중 에 script 태그를 만난 다면?






DOM 파싱됐고 CSS 파서가 작동하게 되는데 여기서 멈춰버리는 현상이 발생합니다.  모든 파싱이 끝나게 되면 지연(async) 모드의 스크립트 에 대한 파싱을 하게 되며

문서 상태는 "완료" 후 "로드" 이벤트 (ex : window.onload) 가 발생하게 됩니다. 


HTML5에서는 해당 의 작업을 위해서 비동기 Script 로딩을 위해서 defer 와 async 라는 속성을 제공합니다. (이외에도 여러가지가있습니다. )


https://developer.mozilla.org/ko/docs/Web/HTML/Element/script  -> Script 태그 


간단하게 알아 보자면 


async :  해당 스크립트를 비동기적으로 실행 

defer :  브라우저의 ㅣDOMContnetLoaded 이벤트 발생전에 작동되어야 하는 스크립트 


** 하지만 2개의 경우는 inline 으로 작성시에는 동작하지 않습니다. 예를 들면 <script aysnc > -> XXX 동작 안됩니다.  JS로 사용시에만 해당됩니다.


그렇기 때문에 Inline으로 태그를 직접 작성하는 경우는 script 태그가 head 상단에 오면 안됩니다.

JS 예 

var fullPath = 'fullPath';
var _script = document.createElement('script');
_script.setAttribute('src',fullPath);
_script.async = true;

document.body.appendChild(_script);
// or
document.body.insertBefore(_script,document.body.lastChild);


해당과 같이 async 에 true를 주었을 때 비동기로 로딩이 되게됩니다. (이에 대해서는 따로 포스팅)


위의 내용을 정리하자면


CSS의 위치는???


문서를 파싱해서 DOM Tree을 만들 때 CSS가 없으면 렌더링을 할수가 없기 때문에  CSS를 가장 빨리 읽을수 있게 합니다. 그렇기 때문에 적합한 위치는


head 태그 사이에 위에 놓는 것입니다.  브라우저 인터프리터에서는 html 파일을 위에서 아래로 읽기 때문입니다.


그럼 CSS를  head 의 가장 맨앞에 놓고 Script 태그를 놓아서 JS를 로딩 시켜도 되지않을까?? -> 위에도 설명 이 되어있지만 Link 태그와 다르게 Script 태그의 경우 파싱 도중 만나게 


되면 파싱 작업을 멈추고 JS를 로드하게 됩니다. 그렇기 때문에 JS파일이 커진다면 사용자 입장에선 로딩 되는 형태로 보여지기 때문에 좋지 않은 결과를 (UX UI )를 


가져올수 있게 됩니다.


혹은 JS가 먼저 실행되어 적용이 되지 않는 형태가 될수도있습니다.( Ex: body 를 그리지 않았는데 DOM 컨트롤을 할 경우 -> undefined 에러 발생 ) 


그렇기 때문에 JS를 로드하는 Script의 경우는


body의 맨 마지막에 위치합니다.


<body>

<!-- do Something -->
<script src="./myLogic.js"></script>
</body>


이렇게 된다면 head태그에 있는 css들이 우선 로딩 된 후 파서들이 바디를 다 그린 후에 -> script 태그를 만나면서


해당 스크립트를 로딩하게 됩니다.


필요한 스크립트들은 해당 스크립트안에서 전부 로딩 시켜주는 형태로 작성을 할려고 합니다.


현재까지 만들어진 페이지의 코드를 보시면


<footer>
<div>
<span class="pages_desc">
ⓒ Gdl Blog Page
</span>
</div>
</footer>
</div><!-- app-root-->
<script src="./lib/gdl.js"> </script>
</body>

</html>



최하단에 gdl.js를 로딩 합니다.


해당 gdl.js에서는


function initialize(){
document.addEventListener("DOMContentLoaded", function() {
console.warn('Windows DOM ContentedLoaded');
gdlUtilModuleLoading();
setTimeout(function(){
gdlOtherModuleLoading();
},100);
// gdlOtherModuleLoading();
});
return{
}
}


보시는 것처럼 UtilModule을 로딩 후


다른 모듈을 로딩합니다.

function gdlOtherModuleLoading(){
var arr = ['gdlAjax','tempEvent'];
// 나머지 모듈 비동기로드
// arr.reduce(function(prev,curr,index,arr){
// Util.include(curr+'.js');
// },0);

// 현재는 동기로드
arr.reduce(function(prev,curr,index,arr){
Util.include({
path:curr+'.js',
jsfileName:curr,
async:false,
onload : function(){
console.warn('임시 테스트 코드 온로드 확인 ',tt);
}
});
},0);


}


보시면 Util.include라는 API(?) 를 사용하였는데요 이거는 제가 따로 함수로 빼놓았습니다.


Util.include는 


Util.include = function(path,configs){
try{
if(typeof path==='object' && typeof configs ==='undefined'){
var configs = path;
path = configs.path;
if(typeof path==='undefined')
throw new Error('path is Undefined');
}

var async =configs!==undefined ?
(configs.async!==undefined ?
configs.async : true) : true;
var pathArr = path.replace(/\.js/gi,'').split('/');
var fullPath = Util.basePath+pathArr.join('/')+'.js';
var jsfileName = configs!==undefined?
(configs.jsfileName !==undefined ?
configs.jsfileName : path) :
path;
var scriptTags = document.createElement('script');
scriptTags.setAttribute('src',fullPath);
scriptTags.async = async;

var onload = configs!==undefined?
configs.onload :
'undefined';
if(typeof onload==='function'){
scriptTags.onload = function (){
onload(fullPath);
}
}
else {
scriptTags.onload = function(){
console.log('onLoad Script >> '+ fullPath);
}
};
document.body.insertBefore(scriptTags,document.body.lastChild);
}
catch(err){
console.error(err);
}
}


lib 형태를 만들고 싶어서 기본 base Path 에 include 할 js들은 gdl.js에서  지정하고 include 합니다.


현재는 동기적으로 하기 위해서 위에 initialize 에서 보시면  async:fale를 지정하였습니다.


해당 index.html 을 console.log에서 확인해보면




위의 코드에서 gdlAjax.js 와 tempEvent.js를  로딩합니다. 


async:false로 지정하였기 때문에 100번을 새로고침해도 같은 형태로 로딩이 됩니다.


테스트 해본결과 async:true 로 하게되면 5번에 1~2번 정도는 순서가 바뀝니다.(비동기 이기 때문)


다음시간에는 해당 페이지를 조금 꾸미고


Button 먼저 만들어 보도록 하겠습니다.


긴글 읽어주셔서 감사합니다!


요즘들어 생각 하고있습니다. 나태해지고 있는 나를 보며  이렇게 살면 안됩니다!! 라고 말을 해야 한다는 걸요


기존에 연차가 낮을  때는 몰랐지만  뭔가 제자리에 있는 제가 연차가 쌓이는걸 너무 보기 싫습니다...


이제는 가만히 있을수 없다고 생각하여


웹의 정말 기본부터 하나씩 포스팅 수를 늘린다는 생각보다는 모든 궁금증에 대한 기본 적인 것 들을 하나씩 하나씩 


최소 차근차근 포스팅을 하려고 합니다.  기존에는 가능하면 하루 이틀에 한번씩 하려고했는데 이게 나태해지면 끝이 없


는 것 같습니다. 하루에 한번 이틀에 한번 이면 좋겠지만 


목표로 하는 바는 바닐라 JS로 컴포넌트 만들어보기 입니다.  한 5개 정도 일단 만들어 보려고 합니다.


기본기가 탄탄해야 된다고 생각해서 웹을 처음한다는 생각으로 다시 접근하겠습니다!!!


VanillaJS


바닐라JS  처음에 이 친구가 무엇을 하는 친구인가 또 어떤 JS인가 궁금했습니다. 


하지만 구글링을 통해 알게 되었죠 때 묻지 않은 순수한 JS라는 걸요 


이친구를 저는 잘안다고 생각 했는데 그리 만만한 친구가 아니였던 것 같습니다.


바닐라 JS에 대한 스터디를 진행하고 그에 대한 내용을 github과 이 도전 카테고리에


공개 할려고합니다. github 주소는 아래와 같습니다.

https://github.com/lgance/reactStudy/blob/master/myVanillaJS/index.html


혼자 공부하는 것들에 대해서 작성합니다. 


해당 내용은 저 자신이 보기 위함입니다. 하하 나중에야 이불킥감 일수 있지만.


컴포넌트를 만드는게 궁극의 목적은 아닙니다. 전반적인 웹의 기본과 브라우저 등에 대해서 공부를 할려고 하기 때문에


저와의 스터디라고 볼수 있겠네요 


github은 때 되는대로 올릴생각입니다.!!


그럼! 다음에 봬용






안녕하세요 정말 오랜간만에 포스팅을 하는 것 같습니다.


ㅜㅜ 회사일이 너무 바쁘네요;;  주말에는 잠만 자구..


사실 이번 포스팅도 조금 억지 스러울 수 있는데요


당연히 포스팅한줄 알았지만


포스팅이 안되어있어서 포스팅하게 되었습니다.


JavaScript를 통한 싱글톤 인스턴스 생성인데요  


Prototype의 경우


Instance = (function(){
function Instance(name){
this.eventObj = {
                "key":"value"
}   

}
// new를 하지 않으면 애초에 생성 불가
Instance.prototype.In = function(module,eventListener){
// this.eventObj 가능
        console.log(this.eventObj);
}
Instance._In = function(module,eventListener){
// this.eventObj 불가능
        console.log(this.eventObj); // undefined
        console.log(eventObj); // ReferenceError : eventObj is not defined
}
    return Instance;

})();


와 같이 this로 객체를 사용하기위해선 모두다 Prototype을 해주어야 합니다.


Instance = (function(){
function Instance(name){
this.eventObj = {
                "key":"value"
}   
}
Instance.prototype.In = function(module,eventListener){
// this.eventObj 가능
        console.log(this.eventObj); // {key : "value" }
}
// _In 은 애초에 사용 불가
Instance._In = function(module,eventListener){
// this.eventObj 불가능
        console.log(this.eventObj);
        console.log(eventObj);
}
    return new Instance;

})();


또한   단순히 Instance로 하여서


var test = new Instance() 로 한다고 하여도


협업을 한다고 가정 하였을 때  저는 


A.js 에서 var test = new Instance(); 하였는데


다른 QA분이 


B.js 에서 var test = new Instance(); 하게되면 


중앙관리가 되지 않습니다. 그렇다보니 싱글톤 패턴을 사용하게 됩니다.(인스턴스는 1개) 


이런 경우는 Prototype을 사용할 필요가 없습니다. 어차피 1개의 인스턴스만 사용될거니간요


테스트 해야 하는 케이스 중 2건 입니다.


//  

onLoad   

(  제품이 최초 실행되는 시점에 발생하는 onLoad 콜백 )


onBeforeLoad

 ( onLoad 전에 실행되는 onBeforeLoad 콜백 )


//


EventListener를 테스트해야 합니다. 해당의 리스너들은 호출이 되었을때 flag형태로 가지게 되는데 


1번 호출 시 true


2번 이상 호출시 false 입니다.


해당에 대한 내용을 확인 할수 있도록 싱글톤 패턴을 사용합니다.



var flag = (function(){
    'use strict'
    var instance;
    
    var topEventObj = {
        "APP":{
        },
        "DOM":{
        }
    }
    function _addEventProperties(obj){
        if(typeof obj !=='object'){
            return;
        }
        // 값 추가
        Object.defineProperty(
            topEventObj[obj.module],
            obj.eventListener,{
                value:true,
                writable:true,
                configurable:true,
                enumerable:true
            }
        )
    }
    function In(module,eventListener){
        if(typeof module ==='undefined' || typeof eventListener ==='undefined'){return;}
        var obj = changeProperties(module,eventListener);
        !!topEventObj[obj.module].hasOwnProperty(obj.eventListener) ?
                (topEventObj[obj.module][obj.eventListener] = false) :
                _addEventProperties(obj);
    }
    function Out(module,eventListener){
        
        if(typeof module ==='undefined' || typeof eventListener ==='undefined'){return;}
        var obj = changeProperties(module,eventListener);
        return !!topEventObj[obj.module].hasOwnProperty(obj.eventListener) ?
                topEventObj[obj.module][obj.eventListener] :
                false;
    }

    function changeProperties(module,eventListener){
        return {
            module:module.toUpperCase(),
            eventListener:eventListener.toUpperCase()
        }   
    }
    
    function initialize(){
            return {
                In:In,
                Out:Out,
            }
    }
    return {
            getInstance:function(){
                    if(!instance){
                        instance = initialize();
                    }
                return instance;
            }
    }
    
})().getInstance();



사용법은 다음과 같습니다.


JS-USE category 이기 때문에  JS에서


IIFE -> Singleton 과 JavaScript Object 에 대해서 다시 한번 설명하도록 하겠ㅅ브니다.



flag.In('app','onload');
flag.Out('app','onload'); // true

flag.In('app','onload');
flag.In('app','onload');
flag.Out('app','onload'); // false


().getInstance()를 통해서 생성과 동시에 flag에 인스턴스를 생성 하였습니다.


원래는 저부분이 빠지고


var test = flag.getInstnace(); 형태입니다.


이후에 var test2 = flag.getInstance로 하여도 이미 생성된 instance가 있기 때문에 새로 객체를 만들지 않습니다.


순서는 단순합니다.


In ->  module과 eventListener를 파라미터로 받습니다.


값에 정합성을 위하여 모든 파라미터를 toUpperCase()를 적용합니다.


var topEventObj = {
        "APP":{
        },
        "DOM":{
        }
    }


해당 객체를  가지고  테스트합니다.

** hasOwnProperty 를 통해서 해당 값이 있을경우는 해당 값을 false로 변경하고


** 없을 경우는 defineProperty 를 통해서 생성합니다.


포스팅을 뭔가 쉬지 않아야 한다는 느낌 때문에


억지로 쓴거 같긴한데 ㅜ


읽어 주셔서 감사합니다.








안녕하세요 오늘은 i태그 <i> 와 <span> 에 대해서 작성하려고 합니다.


태그공부가 다시 제대로 되어야 할거 같아서 작성하게 되었습니다. 네이티브 코드를 다루는 일을 한다면 좀 더 좋을텐데


아니다 보니 자꾸 까먹게 되는 것 같습니다.


i 태그 와 span 태그 에 작성에 앞서 mdn 등 공식 자료를 먼저 보는게 나을거같아요 


이거 먼저 가져 와보겠습니다.


자료는 역시 MDN!


The HTML <i> element represents a range of text that is set off from the normal text for some reason. Some examples include technical terms, foreign language phrases, or fictional character thoughts. It is typically displayed in italic type.


일반적으로는 이탤릭에 사용된다고 하며 어떠한 이유로든 일반 텍스트에서 벗어난 텍스트의 의미!


음...  기존에 (옛날 브라우저) 는 i를 이탤릭 전용으로만 사용하였지만 현재의 i태그는 해당의 의미로는 사용되지 않고


css를 통하여 특정 작업을 하는 형태로 진행되고 있다고 합니다.


i 태그 설정시 기본으로 font-style이 italic으로 들어온 모습




span 태그는


The HTML <span> element is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang. It should be used only when no other semantic element is appropriate. <span> is very much like a <div>element, but <div> is a block-level element whereas a <span> is an inline element.

요약을 하자면 span 태그는 아무 동작도 하지않는 inline 컨테이너 라고 합니다. 

> inline과  inline-block 및 block 에 대해서는 저 깍돌이가 예전에 작성한 적이 있습니다.

> display 형식이라고 보면되는데 그중 span 은 기본적으로 inline형태를 지닌다!    라고 볼수 있겠네요
inline display 에 대해 알면 되겠네용

대표적으로 inline 은 block 과 달리 100%를 차지하지 않기 떄문에

글사이에 색상을 넣는 용도로 쓰는 경우가 많은 것 같습니다.

[span 태그를 통한 색상 변화]








b태그가 기본적으로 굵게 해주기 때문에 b태그 안에 span 을 적었습니다.

<b>inline text in <span>b tag </span></b>
// 관련 css
span{
color: rgb(127, 204, 124);
}




번외


i 와 span 태그를 찾다 보니 i는 icon 의 i로 아이콘 쓸때 사용이 좋다 라는 많은 글들을 보았는데


컨테이너 형식을 가지는 span 이 조금 더 적합하다고 생각되며 부트스트랩 UI같은 플러그인도 최신버전에는 icon 을 


span 으로 사용한다고 합니다.


bootstrap UI Icon (공식홈)














안녕하세요 ! 오늘은 테스트 코드의 특성에 대해 작성하려고합니다.


이것저것 툴이나 lib들만 쓰다보니 기본기가 부족한거 같아 기본서부터 다시 복습을 하고 있는데요


기본서들에 앞장에서는 매번 테스트 코드의 작성에 대해 강조 합니다.


좋은 테스트코드가 있어야 좋은 개발코드가 될수 있고 그는 품질이 높은 코드로 이어지며


품질높은 코드는 품질이 좋은 제품으로도 이어 질수 있기 때문이라고 합니다!



그로 인해서 좋은 테스트 코드에 대한 세가지의 특성을 다음과 같이 설명합니다.


반복성 


테스트 결과는 항상 재현이 가능해야 합니다. 


> 테스트가 반복적으로 실행이 됐는데 다른결과가 나올수 있다고 하면 이 테스트 방법이 과연 맞는 테스트인지 한번 고려를 해보아야 할 것 입니다.


> 또한 테스트 재현을 하는 가능성에서는  네트워크 부하 또는 CPU 부하등의 외부 요인과의 독립적인 테스트 인것이 보장이 되어야 합니다. 


간결성 


테스트는 테스트를 하는 것에만 집중해야 합니다.


> 테스트 코드의 의도 목적을  흐트리지않아야 합니다. 가능한한 많은 HTML 마크업, CSS, 자바스크립트를 제거 하여야 합니다. 많이 제거 될시 테스트 대상이 아닌 코드가 케이스에 영향을 줄 확률이 낮아집니다.


독립성 


각 테스트는 독립적으로 동작이 가능하여야 합니다.


> 현재 실행되는 테스트 가 다른 결과에 의해 변동이되면 안되어야 합니다.  첫번째 내용과 비슷할 수 있지만 현재 작성되는 테스트가 다른 결과에 의존성을 가지게 된다면 버그의 원인을 찾기가 쉽지 않습니다.



이후에는 테스트 프레임워크를 선택하거나 제작하여서 사용하게 되는데 그에 따른


자바스크립트의 Unit 테스트 프레임워크에서 요구되는 기능을 나열하자면


1. 브라우저 의 행동을 할수 있다.

2. 테스트 일시 정지(pause)와 시작(start)가 가능하여야 한다.

3. 비동기 테스트에 대한 setTimeout 

4. 실행되어야 하는 테스트들에 대한 필터링 



이에 해당하는 대표적인 프레임워크


1. Selenium

> E2E테스트에 최적화된 프레임워크 현존하는 테스트프레임워크 중 사견으로는 제일 좋은 솔루션

- 크로스 브라우징 테스트 가능 (ie,firefox,chrome,edge,safari,opera)

- 실제사람이 움직이는 시뮬레이션 가능

- DOM 조작 스크립트 전부 사용 가능(브라우저 Injection 기능을 통함)

- 다양한 언어 지원 (js,JAVA,C#,Ruby,Python)

- 이외에도 더 다양한 기능들 지원 

2. JsUnit


3. YUI Test

> 야후! 에서 개발하고 구축한 테스팅 프레임워크

- 확장가능, 광범위한 단위 테스트 가능

- 비동기 테스트 지원

- 뛰어난 이벤트 시뮬레이션 가능 (http://developer.yahoo.com/yui/3/test/)


4. QUnit

>    jQuery 를 테스트하기 위한 UnitTest Framework 현재는 그이상을 넘어 간결한 솔루션으로 진화

- 가볍고 간결한 API

- 비동기 테스트 지원

- no jQuery 테스트 가능

- Regression Test 에 매우 적합 

> 관련 정보는 http://qunitjs.com


5. FireUnit


6. Screw.Unit


7. JsSpec


8. Dojo


9. Prototype


10. Envjs


11. Jasmine & karma 


12. puppeteer

> 구글에 있는 Chrome 개발팀이 Chrome 테스트를 위해 만드는 프레임워크 

-  매주 패치가 될정도로 활발하게 이루워지는 상태

-  스크립샷 캡처 이미지 비교 등 할수있는 기능들의 매우 많음

- 단점으로는 Chrome에서만 가능 (user-agent를 변경해서 타 브라우저로 뜨게는 가능)

13. mocha & assert


등등이 있습니다.  


위의 프레임워크들이 전부 4가지를 지원하는 것은 아니지만 점유율에 따라 리스트업을 하게 되면 위와같이 나타납니다.


물론 위 말고도 더 많은 테스트프레임워크들이 있습니다. 다 써본건 아니지만 저는 Selenium 을 위주로 사용중입니다.



안녕하세요 <script> 태그를 추가할때 동적 으로 추가 하는 방법 중 하나를 소개하고자 합니다.


JS - USE 포스팅에선 단순하게 코드 위주로 포스팅 하려고 하기 때문에


간단 설명과 


코드 첨부 합니다.


다음 Post 서비스를 cdn 으로 동적 추가 하는 코드 

var daumPostcdnURL = "http://dmaps.daum.net/map_js_init/postcode.v2.js?autoload=false";
		var daumPostCDNScript  = document.createElement('script');
		daumPostCDNScript.setAttribute('src',daumPostcdnURL);
		daumPostCDNScript.onload = function(){
				console.warn('daumPostCDN Script Load Success');
		}
		document.body.insertBefore(daumPostCDNScript,document.body.firstChild);


간단 설명 

1. cdn URL을 설정

 

2. document.createElement 를 통하여 스크립트 생성 


3. setAttribute 를 통하여 src에 해당 url지정


4. 로딩 확인을 위해 onload 콜백 실행 


5. document.body.insertBefore 를 통해 해당 스크립트를 바디 맨 앞에 추가 

안녕하세요 js에서 사용하는 Array 에 대한 메서드에 대해 간단 설명 및 예시로 작성 하려고 합니다.


오늘은 [1] 입니다.  빨간 색 부분은 IE 미지원의 경우 입니다.


** 빨간메서드 부분은 Polyfill이 도입되어야 합니다.


각 함수마다 서포팅 되는 호환성 에 특이 한점은 적도록 하겠습니다.


[1] 에서 작성할 배열 메서드 입니다.

concat(IE 5.5) ,fill, filter(IE 9), findfindIndexincludes, indexOf(IE 9)




[2] 에서 작성할 배열 메서드 입니다.

join, keys, lastIndexOf, pop, push, shift, unshift,


[3] 에서 작성할 배열 메서드 입니다.

some, every, slice, splice, sort, toLocaleString, toSource, values


[4] 에서 작성할 배열 메서드 입니다.

reduce, reduceRight, reverse,  copyWithin, Array.of , Array.from



** 모든 설명은 mdn 을 참조하였습니다.


1. concat 


호환성 :  IE 5.5 이상 동작합니다. (전 브라우저 지원이라고 봐도 될거같습니다.)

description : 인자로 주어지는 배열이나 값들을 기존 배열에 합쳐서 새 배열을 반환합니다. 

깍돌이 설명:  배열1.concat(배열2) 와 같이 쓰면   [ 배열1 + 배열 2 ] 가 된 새 배열3 이 나옵니다.


** 메서드를 호출하게 된 배열 뒤에 인수로 넘어온 배열들을 붙여서 새로운! 배열을 생성합니다.

this나 인수로 넘겨진 배열의 내용을 바꾸지 않고 주어진 배열들을 합친뒤 얕은 복사(shallow copy)

를 리턴 합니다.


Example 1  fruits 배열과 animal 배열의 합치기  (2개)



Example 2  fruits 배열과 animal 배열과 language 배열의 합치기 (3개)



Example 3 fruits 배열에 단일 값 "NinJa" 와  ["QA","devOps"] 를 이어 붙이기

(배열에 값 붙이기)

Example Code


// concat

var fruits =["apple","oragne","grapes","strawberry","watermelon"];
var animal = ["dog","rabbit","horse","chicken","lion"];
var language = ["C","C++","Python","JS","GO"];

// Example 1
var newArray = fruits.concat(animal);
console.warn(newArray);

// Example 2
var newArray = fruits.concat(animal,language);
console.warn(newArray);

// Example 3
var newArray = fruits.concat("NinJA",["QA","devOps"]);
console.warn(newArray);



번외편 !

배열을 단순하게 + 로 더하면 어떻게 될까 ?

문자열이 됩니다.! ( 하지만 자세히 보면 watermelondog 로 붙어있는 부분이 있습니다. )

[... 끝]+[처음...]이 붙는 부분에서 "끝처음" 로 붙네요 쓸순 없습니다. ㅎ_ㅎ




2. fill


호환성 : IE,Opera는 아예 지원되지 않습니다.  (Chrome 36이상 FireFox 31이상 Safari 7.1이상)

폴리필을 사용 하여야 합니다.  // 폴리필 주소

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/fill

description : 배열의 시작인덱스부터 끝 인덱스까지 정적 값으로 배열 요소들을 채웁니다.


깍돌이 설명:   배열을 정해진 특정 값으로 채워넣기 위해 사용하는 함수입니다. (react에서 자주 사용합니다.)


** 해당 메서드를 사용한 배열의 원본 값이 변합니다. 주의 !!


Example 1  fruits 배열을 4로 채우기 



Example 2  fruits 배열을 2부터 4로 채우기 2부터에서 2는 index입니다(0부터시작)


Example 3  fruits 배열을 2부터 3까지만 4로 채우기  2에서 3은 index입니다.


** 특이사항 : 시작하는 start는 현재 인덱스를 포함하지만 end는 그 전 인덱스까지 입니다.
Example 4  fruits 배열의 start를 -1로 시작 
** 음수일 경우     start + length (배열 전체 길이 )
이기 때문에 현재 배열의 길이는 5이기 때문에 5 + - 1 이 되어서 fruits[4] 부터 4값이 들어가게 됩니다. 


Example 5  fruits 배열의 start를 -2로 시작 
** -2 + 5  = > 3 이기 때문에 index[3] 부터 4가 들어가게 됩니다. strawberry 부터 4값이


Example 6  fruits 배열의 end 를 -1로 시작
** 음수일 경우    end +  length (배열 전체 길이 ) > start와 형태가 같지만
start는 해당 위치부터
end는 해당위치까지입니다.

react 에서 순수 위젯 리스트를 표현할때 사용하기도 합니다.
const btnList = Array(this.props.count).fill(null).map((i,index) =>{
return <button type="button" style={btnStyle} key={"Btn_"+index} >
{this.props.name +"_"+index}</button>;
});





3. filter


앗.. filter부터 안써놓은지 몰랐습니다. ㅜㅜ 새롭게 다시 작성해서 채우도록;; 하겠습니다.'



호환성 :  IE 브라우저 9 이상 지원합니다. 

description : 조건에 맞는 함수를 통과하는 요소를 모아 새로운 배열로 반환 합니다.

깍돌이 설명:  특정 조건에 맞는 배열을 새롭게 반환시켜주는 함수라고 보시면 될 것 같습니다.


var fruits =["apple","oragne","grapes","strawberry","watermelon"];
fruits.filter(function(ele,index,arr){
    return ele.length >= 7; // ['strawberry','watermelon']
});






4. find


호환성 :  IE미지원

description : 

깍돌이 설명:  IE를 미지원하기 때문에 폴리필 코드가 필요합니다.

 


** 

Example 1  


5. findIndex


호환성 : 

description :

깍돌이 설명:  


** 

Example 1  


6. includes


호환성 : 

description :

깍돌이 설명:  


** 

Example 1  


7. indexOf


호환성 : 

description :

깍돌이 설명:  


** 

Example 1  




안녕하세요 


자사에 있는 제품중인 UI 제품군 중 TOP라는 웹 프론트앤드 프레임워크 의 QA를 맡고 있습니다.


우선 자동화에 대한 설명에 앞서 TOP 에 대한 설명을 제가 직접 할순 없기에 오피셜로 있는 링크를 올립니다.



해당 TOP 에 대한 공식적인 소개

https://tmaxos.com/index#TOP

(소개 페이지였었지만 지금은 TOP로 개발한 홈페이지가 되었습니다) 


기본적으로 Tool + web framework 형태인데


오늘 포스팅 할 내용은 web framework 에 대한 자동화 이야기 입니다. 


IDE라고 하는 tool 자체에 대한 자동화 이야기는 다음에 작성 할 예정입니다.


비즈니스 프레임워크 중에 는 이례적? 이라고 해야할까요 최신 웹 프레임워크의 트렌드를 가진 프레임워크 입니다.

(SPA,Router,Controller,CSR... 등등)


또한 사용자가 만들어야 할 html 코드를 최소화 하여 Data 형태 만  정하게 되면 화면에 나타날수있게 도와줍니다. 


해당 프레임워크에서는 위의 링크와 같이 화면을 구성하기 위한 수십개의 컴포넌트와 컨테이너 등을 제공하게 되는데


그럼과 동시에 해당 컴포넌트들은 크로스 브라우징 형태로 제공이 되기 때문에 지원하는 브라우저가 많아지는 경우


중복하여 확인하여야 하는 작업 이 너무 많아지게 됩니다.


그렇기 때문에 해당 테스트를 자동화 하기 위한 Selenium WebDriver(Node.js)  Jenkins 를 사용하여서 하나의 


Selenium 프로젝트에서 여러 운영체제 및 브라우저(Chrome,FireFox,Internet Explorer, Opera, IOS Safari, Android ) 에 


대한 테스트를 자동화를 하여야 합니다.



이와 관련하여서는 기존에 포스팅 하였던 자료가 있지만 좀더  구조적으로 설명 하며 개요 부터 설명 하도록 하기위해 


다시 작성하였습니다.


// 기존 자동화 링크 

https://ipex.tistory.com/entry/Jenkins-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A7%81%ED%81%AC-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EC%97%B0%EB%8F%99-3-%EB%B2%88%EC%99%B8-Iterative-Test-Build-Steps-%EC%82%AC%EC%9A%A9%EC%97%86%EC%9D%B4-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A7%81%ED%81%AC%EC%97%90-%EC%BC%80%EC%9D%B4%EC%8A%A4-%EC%8B%A4%ED%96%89-TestCase-Execution-into-TestLink-without-Iterative-test-build-steps-on-JENKINS



프론트 프레임워크와 기존 웹 페이지 자동화의 차이점


  기존의 화면 (페이지가 만들어져 있는) 에 대한 자동화와 프론트 프레임워크 에 대한 자동화는 차이가있습니다.


            화면 자동화의 경우 A페이지 (로그인 페이지) 일 때




아이디 창에 대한 E2E 테스트가 진행된다고 하면 개발할때 의 스펙에 맞게만 테스트가 진행되어야 합니다.


ex : 50자 최대 일 경우 (50자이상입력이 되는지 )

ex : id만 입력 후 로그인 시 "비밀번호를 입력해주세요" 메시지가 하단에 출력되는지 .

ex : 아이디 입력 후 "엔터" 키 입력 시  "비밀번호" 창으로 이동이 되는지 


해당 화면은 "로그인페이지" 에만 존재하기 때문에 해당 케이스 또한 로그인 페이지에서만 유효한 케이스라고 볼수 있습니다.


하지만 "아이디 입력창" + "비밀번호 입력창" + "로그인 버튼" 이 한개의 컴포넌트라고 보게 됐을경우


<naverLogin-tag> 와 같은 형태로만들어지는 컴포넌트라면 이야기가 달라집니다. 

get함수를 통해서 현재 id pw 가 {id: "",pw:""} 받을수도 있고 하나의 컴포넌트로서 기능적인 면이 들어가기 때문입니다.


컴포넌트를 테스트하는 것과 웹 페이지를 테스트 하는 것은 다르다 


TOP에서는 이런 형태로 수십개의 컴포넌트를 제공하고 있습니다. 단 하나의 태그와 원하는 데이터 형태 로 


사용자가 작성하는 html 태그가 최소화 되는 형태로 제공됩니다.


그렇기 때문에 QA 입장에서는 위젯, 레이아웃,컨테이너가 있을 경우 각각 의 모든 케이스가 TC(테스트케이스) 가 됩니다.


레이아웃은 위젯을 배치하는 컴포넌트이고 위젯은 레이아웃에 배치되는 컴포넌트 컨테이너는 데이터를 표현하기 


위한 컴포넌트 라고 봤을때


A레이아웃  + B 위젯  + C 컨테이너만 놓고 봐도 세개의 컴포넌트에서만 케이스가 무수하게 나옵니다.


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ


A레이아웃 안에 C컨테이너를 배치시 화면에 렌더링 되는지

A레이아웃 안에 B위젯을 배치시 화면에 렌더링 되는지

A레이아웃 안에 B + C 컴포넌트가 같이 있을시 같이 렌더링이 되는지

.....


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ


그런데 문제는 하나하나 다 컴포넌트 형태이기 때문에 


각각이 제공하는 API 가있고 속성이 있습니다. 


A레이아웃 - C 컨테이너로 테스트하는데 


C컨테이너에 자체 속성이 20개 API 가 20개 일 경우 단순 무식하게 TC(테스트케이스) 를 만든다고 하면 이 숫자 또한 만만치 않게 됩니다.


그래서 원칙적으로는 페어와이즈 테스트 기법을 통해서 케이스를 추출 + 사용자들에 의해 발생하는 회귀테스트 를 우선 작성하고 이에대한 자동화를 진행하게 됩니다.




SeleniumWebDriver (Node.js) 를 사용하는 이유


  Selenium Webdriver Node.js 를 사용한 이유는 우선적 으로 말씀드리자면 JavaScript를 좀 더 많이 쓰기 때문이였습니다. 

하지만 단순히 이런 이유로 사용하기에는 자동화를 하기 위해 좀더 찾아 본 결과로는 SeleniumWebDriver 를 최초의 만들었던 제작자 가 기존의 JAVA 등의 버전에서 현재 js진영으로 넘어와서 새로 프로젝트를 하고 있기 때문이다.(링크를 하려 하였으나 아직 못찾아서 찾는대로 링크하겠습니다.)



[셀레니엄hq 공식 홈페이지]

https://www.seleniumhq.org/download/



Node.js 의 진영은 보시다시피 메이저 버전이 업된 4.0.0 alpha버전임을 확인 할수 있으며  npm 다운로드 수 또한 매우 높아 해당 셀레니움으로 사용하게 되었습니다. 결론적으로 사용하게 된 이유는


정리를 하자면 

  1. 가장 버전이 높은 (활발하기때문)

  2. 사용하던 js언어와 호환성

  3. Node 에서 할수 있는 기능 (xml포매팅 , 파일 관리 등) 을 같이 사용 가능 (리눅스,윈도우 세팅의 편리)

  4. E2E 에서 여러 브라우저를 직접 실행하여 사용가능 ( 하나의 테스트프로젝트를 통해 여러 브라우저에서 테스트 가능 ) 


이외의 알아본 lib 들은 


phantom.js && capser.js , zombie.js slimer.js , webdrivero.io, Cucumber.js , protactor, 

nightwatch.js htmlUnit,Guitar,Cypress.io,uitest, uirecorder,testCafe(*typeScript) 


정도 나열할수 있지만 이러저러한 이유로 사용하지 않았습니다.

 (기본 베이스가 셀레니움이거나, 크로스브라우징에 적합하지않음 등등)



[NPM 다운로드 수 및 이슈]

위의 사진만 비교해봐도 (2018-11-05) selenium-webdriver를 선택 한 점을 찾을수 있다.



SeleniumWebDriver 와 Jenkins 를 사용시 이점 


정확히는 소스코드를 Git으로 관리하게 되는데 이것을 이용한 사용에 대한 이점도 충분히 있습니다.


테스트 자동화 라는게 단순 자동화 를 해주는 SeleniumWebDriver만 이 아니라 일련의 작업

( 최신의 테스트 코드로 테스트를 진행 하고 결과를 리포팅 하는 작업 까지 )


자동화 프로세스




SeleniumWebDriver 코드 작성 



isDisplayDOM 사용 


Chrome브라우저의 경우 속도가 매우 빠릅니다. 타 브라우저에 비해서 그렇기 때문에 단순히 DOM Select 하고 클릭하고

다른 작업으로 넘어 가도 문제가 없지만 IE의 경우에는 이속도가 보장이 되지않는 경우가 많습니다.

(자동화 작업중 트러블 슈팅은 거의 IE에서 일어납니다. ㅜ) 


그렇기 때문에 자체적으로 테스트할 위젯 (클릭하거나 조작할 DOM Element) 를 가져올때 isDisplayDOM 이라는 함수를 만들어서 사용하게 됩니다. 




let startIdx=0;
let retTarget = await this.isDisplayDOM(id);
let tbody = await retTarget.findElement(By.css('table > tbody'));
let totalRowArray = await tbody.findElements(By.css('tr'));


isDisplayDOM 구현체


구현체는 생각보다 단순합니다. driver.wait 라는 API 를 이용해서

until(Util 관련 모듈 입니다.) 을 이용하여서 elementLocated  대상 element가 브라우저 DOM에 붙을때까지 기다립니다.


뒤에 maxWaitTime 같은 경우는 QA가 최대 대기 시간을 작성해놓습니다. 저는 2초 정도로 하였습니다. 2초안에 DOM 에 붙지 않는 다면 해당 테스트 케이스 및 시나리오는 실패로 간주합니다.

(2018-11-20 ) 해당 함수에는 아직 selector 처리가 없네요 id또는 tag , selector로 가져올수 있기 때문에 이부분에 대한처리도 같이 해줘야

진정한 모듈함수 


topqa.prototype.isDisplayDOM = async function(targetId){
let maxWaitTime = 2000;
try{
// let target = await this.driver.findElement(By.id(targetId));
let target = await this.driver.wait(until.elementLocated(By.id(targetId)),maxWaitTime);
if(targetId === await target.getAttribute('id')){
console.log("checked DOM is : ",targetId);
return await target;
}
else{
return false;
}
}
catch(err){
console.warn("isDisplayDOM Error : ",targetId)
console.error(err);
}
}; // isDisplayDOM



해당 과 같이 작성해서 사용하게 되면  DOM 뜨고 나서 진행되기 때문에 중간에  DOM 을 캐치하지못하여 종료되는 오류는 막을수 있습니다.




해당 최신 코드는 


https://github.com/lgance/selenium_tmax/blob/master/topqaModule/autoManager.js


에서 보실수 있습니다!! ( 2019년 에 퇴사를 하여 최신화를 진행하진 않습니다.)





김판순 김치찌개

메뉴 : 김치찌개 (3인) 27000 + 라면사리 2,000 +  왕 계란말이(7,000)

total : 36,000원


후기 

깍돌이 : 김치찌개 인당 돼지고기 들어가있는데 진짜 핵맛! 뒤에 라면사리도 하나 넣으면 끝..

깍돌이 친구들 : 김치찌개를 왜 돈내고 먹는지 알게 해줄게



+ Recent posts