안녕하세요 모두들 새해복 많이 받으세요

 

지금은 아니지만 예전에 맡았던 제품중에 SPA Web IDE 제품을 맡은적이 있었습니다.

 

해당 제품을 맡게되면 품질도 검증하지만 실제 페이지 개발을 많이 하게되는데 이부분에서 기본기 및 Native 스킬들에 

 

대해서 많은 공부를 하게되었고 혼자하다보니 독학으로는 쉽지 않았던 부분들이 있어서 많은 시간을 들여서 공부던 기

 

억이 누군가를 도와줄수 있으면 좋겠다 정확한 지식을 전달해주고싶다라는 마음이 있어서 커뮤니티들을 돌아다니면서

 

질문도 하지만 답변도 해주는 식의 활동들을 하면서 내가 이해했던 부분들을 글로 작성하려니 제대로 이해를 해야

 

작성할수 있구나 라는걸을 느끼게 되면서 티스토리 블로그도 작성하게 되었습니다. 

 

그러던 와중에 마주치게된 NAVER Boost Course !

 

네이버 메인에서 발견한 NAVER Boost Course 의 리뷰어가 된다면 리뷰어가 되기까지 2달간의 테스트를 거칩니다.

 

                  프로젝트 테스트 -> 프로젝트를 리뷰하는 리뷰 품질 테스트 

 

두 달간의 테스트를 거친 후에 리뷰어로 발탁이 될수있기에 정말 좋은 기회라고 생각이 되어서 지원을 하게 되었고

 

2019년도 에 수강생들의 코드를 리뷰 하면서 활동했던거 같습니다. (상반기에만 너무 집중적으로 ㅜㅜ... 하반기엔 거의 못했네요)

 

리뷰어로 활동을 하면 소정의 활동비가 지급되지만 활동비가 목적은 아니였기에 1명의 수강생의 리뷰를 할때는 개인적

 

으로는 하루 날을 잡고 했던거 같습니다. (유료로 코드 리뷰를 신청한 수강생에게 실망감을 주고 싶지 않았습니다.)

 

코드를 리뷰하면서 알고있던 지식도 다시한번 조사해보고 평소에도 더 좋은 기본기와 코드를 알려줄수 없을까 이곳저곳 자료 조사도 하고 코드도 짜보고 트렌드 조사도 했던거 같습니다.

 

2019년 하반기에는 개인적 인 변화가 있었는데요 "이직" 을 하게되었습니다.  코드리뷰의 경우 높은 코드리뷰 품질을 

 

드리고싶어 하루를 사용했었는데 하반기에는 개인적인 공부를 하게되어  하루를 쓸시간이 없었던거 같습니다. (아마 하루는 있었겠지만)

 

그대로 1년의 활동이 지나 2020년이 되었고 퇴근 후 집에 도착해보니

 

커넥트 운영진에서 작은 선물을 보내왔었네요!

 

 

 

 

랑 텀블러가 왔습니다. 처음으로 노트북에 스티커를 붙여보네요 ㅎㅎㅎ

 

커넥트 운영진 들 2019년도 동안 감사했습니다. 

 

 

 

 

 

 

ICST(International Conference on Software Testing Verification and Validation) 2010 발표

구글의 개발 단계별 결함 수정에 들어간 비용 에 대해서 작성한 자료를 보면

 

개발자가 테스트 주도 개발(Test Driven Development, TDD) 과정에서 결함을 발견시 5달러의 비용을 줄일수 있지만 QA단계인 시스템 테스트 과정에서 발생한 결함의 경우 5,000달러의 품질 비용을 줄일수 있다는 것 

 

이런것을 보면 적용시기가 문제이지 품질에 시스템을 적용하는건 비용의 문제가 아님을 보여주는 계기가 된다.

 

 

잔존 결함 밀도, 코딩표준 준수율, 코드 리뷰 수행률, 중복 코드, 코드 복잡도 

 

 

 

feat. NHN 은 이렇게 한다 !  소프트웨어 품질관리 

Concurrent Connection Test  일명 CC Test 라고 불리우는 TCP 같은 연결에 동시성 테스트를 해야 할 경우

 

에 JMeter를 간단하게 사용한 후기입니다.

 

Apache JMeter 

JMeter의 경우 부하테스트 기능과 성능을 측정하기 위해 디자인된 100% 순수 자바 애플리케이션이라고 소개 되었습니다. 

실제로 실행해서 보면 java 를 CLI 형태로 실행 하는 모습을 확인 할수 있습니다.

JMeter에 대해서는 한번 자세히 따로 포스팅 하도록 하겠습니다. (테스트 쪽에)

 

이번에는 설치 과정은 제외하고 작성 하겠습니다. 간단한 활동이기도 했고

https://jmeter.apache.org/download_jmeter.cgi

 

Apache JMeter - Download Apache JMeter

Download Apache JMeter We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hours) may not yet be ava

jmeter.apache.org

여기서 다운받고 설치 하면 끝! 입니다.

 

Thead Group 

처음에 설치 후 실행하게되면 TestPlan 이존재할텐데요 일단 Test Group 을 우릭으로 생성 해줍니다.

 

 

HTTP Request 설정 

해당 TestGroup 에서 Http Request를 생성합니다. 해당 작업에서는 내가 어디 서버로 부하를 줄지 에 대한 

 

 

 

Thead Group 설정

해당 설정에서는 유저의 수를 정할수 있습니다.

Number of Thread(users) : 유저수를 정하며 100으로정하게 되면 100개의 쓰레드로 실행하기 때문에 동시성이 가능합니다.( 저는 3000으로 했습니다. - 컴퓨터가 날아갑니다.)

Ramp-up period ( inseconds) : 준비시간을 의미합니다. 

Loop Count : 위에 HTTP request를 해당 유저들이 몇번씩 할건지에 대한 이야기입니다.

                  A URL로 3000인 상황에서 10이면 ( 3천명이 10번씩 -> 3만번 호출) 이 될수있겠네요

 

Thead Group Listener 

어떻게 보면 매우 중요한 부분입니다. 해당 위의 테스트 한 내용에 대한 결과를 보는 부분인데요

이중에서 제가 자주 쓰는 2가지만 일단 간단하게 소개하겠습니다.

 

 

 

View Result Tree

Http 가 호출을 했을 때의 결과를 Result Tree로 보여줍니다.

아래와같이 성공한경우는 초록색 실패한 경우는 빨갛게 나오며 클릭시 해당 내용을 확인하실수 있습니다.

 

 

Summary Report

많은 호출개수와 에러율 쓰루풋 정도가 확인되는데요 간단하게 요약 형태로 나오는거라 자주 애용합니다.

 

 

 

여기까지 정말 간단하게 JMeter를 알아 보았는데 사실 JMeter는 엑셀을 가지고 연동하여서 쓰는 방법도 많고 

 

활용방안이 무궁무진합니다. 해당을 이용하여서 업무에 적용시마다 하나하나 소개할 예정입니다. 

 

감사합니다.

 

** 제 가 사용하는 PC가 dell XPS 8930 을 사용하는데 3000명이 1000번 호출은 PC가 못버팁니다. 

1000명이 1000번 호출은 간신히 버팁니다. 사용하시는 분들은 참고하세요~

 

 

 

 

 

최근에 QT 를 사용하게 될 일이 있어서 이에 대해서 기록차 글을 한번 끄적 거려 봅니당

 

web 쪽 QA를 하고 있다보니 우리 제품으로 제작된 페이지가 잘 구동되는지에 대해서 검증을 하게 됩니다.

 

IE( 10, 11 )  , Chrome, FireFox 최근에는 Safari 도 추가하려는 움직임이 스물스물 

 

하지만 이번에는 조금 특이한 케이스가 있었습니다.  제품을 구매하는 고객사에서는 webView를 사용하여 

 

모든 프로그램들이 구동이 되는 환경 인것 이였습니다! 그렇기 때문에 우리도 그에 맞춰서 우리의 제품 들

 

또는 QA에서 제작되어있는 페이지들이 정상적으로 구동이 되는지를 확인 해보아야 합니다.

 

WebView의 경우는  webkit이라는 엔진을 사용하기 때문에 Chrome이랑 같겠지! 라고 생각 하면 오산입니다.

 

어찌됐든 C++프로그램에 올라가는 형태로 진행이 되는 것 이기 때문에 어떠한 동작에 대해서는 다른 결과를

 

가져올수 있기 때문입니다.

대표적으로 webView에서는 openWindow가 되지않습니다.

정정합니당 Default Settings으로 webView에서 openWindow가 되지않습니다.

탭을 하나 새로 켜야하지만 C++ 프로그램에서는 없을 수 있기 때문이죠

 

재빠르게 QA가 만들어놓은 페이지를 검증 후 우리회사의 제품 을 검증해야 하는데 처음 하게되는 제품에 대해서는

 

빠르게 체크리스트를 작성하여 Pass, Fail 을 기록 하여 전달하는 것이 업무 전달에 조금 빠르게 진행 할수 있을

 

거라고 생각 하였습니다.

 

하지만 사용해야 하는 버전은 5.9.X 버전 qt 코드 작성 예시를 찾다 보면 webView의 코드가 단순하게 나와있습니다.

 

(QT를 설치하는 작업은 생략 하였습니다. 단순하게 

 

Main.cpp

#include <QtGui>
#include <QtWebKit>

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    QWebView view;
    view.show();
    view.setUrl(QUrl("http://google.com"));
    return app.exec();
}

Main.pro

QT += webkit
SOURCES = example.cpp

 

이와 같이 말이죠  이렇게 한번에 된다면 정말 좋겠지 만요 QT는 5.5 이후로 webView가 빠져있습니다. 

 

두둥... 그렇습니다. qmake 사용시 Unkown Module(s) webkit 을 보게 됩니다.

 

5.9 버전에서는 webView가 없기 때문에 마찬가지로 QTCreator에서도 WebView는 존재하지 않습니다.

 

그래서 동작하지 않게 되는데 webkit을 깔거나 이것저것 여러가지 시도를 해보았지만 webkit을 따로 붙이는 작업을

 

하다가 더 빨리 웹뷰를 띄워야 한다는 요청이 있었어서  5.9.X Documentation QT를 들어가서 확인해 보니 

 

webEngine을 이용한 방법이 있었습니다.

 

Main.cpp

#include <QWebEngineView>
#include <QApplication>
#include <QUrl>

int main(int argc, char ** argv){
	
    QApplication app(argc,argv);
    
    QWebEngineView *view = new QWebEngineView();
    view->setZoomFactor(0.7); // 배율 조정 API 테스트 를 편하게 하기 위해 추가
    view->load(Qurl("테스트 url"));
    view->show();
    
    
    return app.exec();
}

MainSample.pro

QT += webenginewidgets widgets core gui

... 

실행 결과

 

 

** 포스팅에서 제외된 부분 

필요한 Module들에 대한 에러 메시지가 나타날 경우 해당 관련 제품들을 설치 하였습니다.

 

감사합니다.

 

QA업무 중 TC(일명 : TestCase) 에 대한 구조를 짜는 도중


오랜만에 자료구조에 대해 고민하게 되었습니당... ㅎㅎ(사실 이런 고민거리 너무 좋은.. ㅎㅎ)


QA 업무 중 자료구조 ? 1탄

https://ipex.tistory.com/entry/QA-%EC%97%85%EB%AC%B4-%EC%A4%91-%EC%9E%90%EB%A3%8C-%EA%B5%AC%EC%A1%B0?category=666717


여기에 있는 TestCase 를 전체 순회 하는 작업을 하게 되었는데


일을 하다보니 정말 시간이 안나서 저녁먹고 7시쯤 됐나 이슈를 연구소에 다 전달하고 하니


시간이 붕 떠버렸습니다. 그래서 퇴근을 하려고했지만 해당 순회에대한 작업이 안되서 계속 신경이 쓰여버리는 바람에


시간을 내서 한번 level-순회에 대해서 조사를 해보고 실행해 보았습니다.


일단 구조는 전체 포스팅했지만 대강 이런 구조입니다.


장점이라 함은


특정위젯에 특정 카테고리에 있는 케이스를 가져올때 너무 편합니다.


예를들어


widget 에 setFocus API를 가져와야 한다.


obj.widget.api.setFocus

obj["widget"]["api"]["setFocus"]  두 방식다 사용할수 있기 때문이죠 되도록이면 

"전자"(obj.widget.api.setFocus) 의 방법을 사용하는게 좋다고 하네요!


하지만 문제 되는점은 특정 위치에서 전체 케이스를 가져올 때 입니다.


widget 에 api 를 전부 가져와야 한다!


모든 tc를 가져와야 한다.

결국은 특정 "Root"를 기준으로 Leaf Node 를 가져올수 있어야 한다는 의미가 됩니다.


다음 설명은 그림을 지나서 슈슉


자 이제 여기서 LeafNode(마지막 노드) 를 가져와야합니다. 마지막 노드! 여기서는 테스트케이스 겠네요


level - 순회 트리에서 중요한거는


(preOrder, postOrder, inOrder)전위순회,후위순회,중위순회 와는 다르게 "레벨" 별로 순회를 해야한다는 점입니다.


그렇기 때문에 등장하는 개념이 바로 큐(Queue) 입니다.



레벨 트리 순회는 위의 그림처럼 레벨별로 순회를 하여야 합니다.


A 레벨 순회 -> B레벨 순회 -> C레벨 순회 -> D레벨 순회


재귀형태로 도는 기본 순회랑은 조금 다르다고 볼수있습니다.


각 레벨별로 큐(Queue)를 두어서 해당 큐(Queue)에서 레벨을 관리 할수 있도록 하는 방법입니다.


그렇기 때문에 시나리오를 그려본다면


순회를 할 함수 ! 


리프노드인지 체크하는 함수 !


2개 정도가 필요할것 같구


순회 하는 함수에서는 처음으로 Root 노드를 파라미터로 받아 Child(자식) 값이 있을 경우 해당 내용을 큐에 넣고


큐는 다시 앞에서 부터 꺼내서 Child(자식)이 있으면 다시 그 자식들을  큐(Queue) 에 넣고 없다면 leafNode라는 배열에 


추가 해주는 방식을 사용하였습니다.


말로만 백날해봐야 백문의 불여일견이죠


코드로 보자면


1번 리프노드 체크


function isLeaf(node){
var leafKey = Object.keys(node);
var isLeaf = true;
var length = leafKey.length;

for(let i=0;i<length;i++){
if(typeof node[leafKey[i]]==='object'){
isLeaf = false;
}
}
return isLeaf;
}


생각보다 단순하죠  해당 노드의 내부 Value 들이(js Object는 key : value 로 구성됩니다.) 전부 object가 아니면 되는


케이스입니다. 사실 리프노드의 체크 유무는 원하는 상태에 따라 다를수 있기 때문에 저는 이번에 이런식으로


체크했다고 아시면 될 것 같습니다.


2번 루트 노드 순회 


function levelTree(obj){
var Queue=[];
var leafNode = [];
Queue.push(obj);
while(!__isEmpty(Queue)){
// dequeue
var root = Queue.shift();
console.log(root);
// 리프 노드가 맞다면
if(isLeaf(root)){
leafNode.push(root);
}
// 리프 노드가 아니라면 해당 자식들을 전부 큐에 추가
else{
let keyArr = Object.keys(root);
let length = keyArr.length;
for(let i=0;i<length;i++){
Queue.push(root[keyArr[i]]);
}
}
}
return leafNode;
}


사실 루트 노드 순회도 너무 별게 없다보니 이걸.. 적어야 하나 말아야 하나 고민했습니다.


순회 하기전에 Queue를 하나 만듭니다.


Q : [] 겠네요


그리고 바로 obj 를 추가합니다. 


만약 var obj = {

 "test":{},
"testb":{} 

}

이라면


Q : [obj] 가 되겠죵


그리고 while문을 돌리게 되는데 __isEmpty는 제가 따로 구현한 형태입니다. 비어있는지 아닌지만 판별해서 return 


while -> 간단하게 설명하면 Queue가 비어있으면 나가는 게 조건입니다. 


Queue생성후 push 를 해주었기 때문에 비어있지 않아 while 문으로 들어가게 됩니다.


그리고 Queue이기 때문에 js에서는 pop이 아닌 shift를 빼옵니다. 그래야 Queue의 FIFO 구조가 성립이 되기때문이죠


var obj = {
"widget":{
"api":{
"setFocus":{
"contents:":"setFocus쥬",
"tc":"WIDGET_API_SETFOCUS",
"result":"fail"
}
},
"event":{},
}
,
"widget2":{
"attr":{},
"event":{},

}
}


해당의 obj가 들어온다고 가정하고 그림을 그리면 Queue는 Q , Root는 현재 방문중인 노드로 R이라고하겠습니다.


while문 전에


Q [ obj ]

R  undefined


Q.shift 후


Q []   

R obj ("widget","widget2") 키값 2개 리프노드가 아님


Q에 추가


Q [ "widget", "widget2"]

R  -


Q.shift()


Q ["widget2"]


R  "widget"     ("api","event") 2개 있음  역시 리프노드가 아니기 때문에 push


Q에 추가 


Q ["widget2","api","event"]


R   - 


Q.shift()


Q ["api","event"]


R "widget2"   "attr","event" 2개를 가지고있으며 역시 리프노드가 아님 push


Q에 추가


Q ["api","event","attr","event"]


R


Q.shift()


Q ["event","attr",event"]


R "api"      "setFocus"를 가지고있음 리프노드가 아님


Q에 추가


Q ["event","attr","event","setFocus"]  


> 이후에 전부 하위 자식들을 추가하다가 setFocus를 만났을때


Q ["setFocus", .....] 에서 Q.shift()


Q [......] 


R "setFocus" 리프노드를 확인하면 내부값이 전부 string으로만되어있어 리프노드 true가 나타나게됨



leafNode.push(root);


체크가확인되면 리프노드에 추가


위의 방식으로 계속 순환후 함수에서는 leafNode를 return


** 실행 결과




테스트용이였지만 단순하게 {}로만 되어있는것들도 리프노드로 가져왔네요 문제 될건 아니지만 이런 경우도 나중에 다시


수정해야 할 부분이겠죠!


트리순회는 이만 마치도록 하겠습니당



전체 코드 (테스트용 코드이며 업무시에는 모듈 형태로 변환하여야 합니다.)




function __isEmpty(array){
return array.length===0 ? true : false;
}
function getShow(){
var leafArray = levelTree(obj);
console.warn(leafArray);

}

function levelTree(obj){
var Queue=[];
var leafNode = [];
Queue.push(obj);
while(!__isEmpty(Queue)){
var root = Queue.shift();
console.log(root);
if(isLeaf(root)){
leafNode.push(root);
}
else{
let keyArr = Object.keys(root);
let length = keyArr.length;
for(let i=0;i<length;i++){
Queue.push(root[keyArr[i]]);
}
}
}
return leafNode;
}
function isLeaf(node){
var isLeaf = true;

var leafKey = Object.keys(node);
var length = leafKey.length;

for(let i=0;i<length;i++){
if(typeof node[leafKey[i]]==='object'){
isLeaf = false;
}
}
return isLeaf;
}

























업무 중에 자료 구조를 쓸일이 있을까? 라는 생각을 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가 이 속도를 따라 올수 있냐의 유무를 실제 적용해보지 않고서는 


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













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


이것저것 툴이나 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 을 위주로 사용중입니다.



안녕하세요 QA 인데 qa자료가 제일없는거 같아서 조금 그렇네용...



오늘은 IE11버전 이하 IE 10버전 부터 발생하는 이슈 중 특이한 이슈가 있어서 작성하게 되었습니다.


시작은 즉슨 .. IE 9 버전에서 기능이 이상합니다.! 라는 이야기와 함께 찾아봤습니다.


준비물


window.onbeforeunload  && a 태그와 href 속성


요약 

a태그가 눌릴때마다 window.onbeforeunload 가 호출되는 현상 IE 구버전에서 발생하게됩니다.


내용 

<a href="javascript:pay();" class="btn_b btn_red"><span>결제하기</span></a>


 와 같은 코드가 있을때


해당 DOM 에 만약에 window.onbeforeunload 가 들어가 있을 경우


해당 a태그가 클릭될때마다 onbeforeunlaod에서 작성된 함수가 계속 실행됩니다.


노답 버그!


해결법

1번 href를 쓰지 말고 onClick 을 사용합니다. 


2번 의 경우는 오류가 났던 사이트 개발자 분이 직접 이렇게 사용하여서 해결했다고 합니다. 


jQuery 를 사용한 방법인데요


$(window).data('beforeunload',window.onbeforeunload);

     $('a[href^="javascript:"]').hover( 

        function(){window.onbeforeunload=null;},

        function(){window.onbeforeunload=$(window).data('beforeunload');}

    );

약간의 꼼수(?) 느낌으로 이렇게 해결했다고하네요


약간의 설명이들어가자면     $('a[href^="javascript:"]').hover( 

는 a태그중 href속성에서 javascript: 로 시작하는 모든속성에 대한 .hover 작업입니다.


아래의 hover 속성에 보면 param 으로 2개가 들어가있죠 , 로 나눠져있는걸 보면


jQuery 를 안쓰는 요즘 분들? 또는 jQuery 자체를 안쓰시는 분들은 이해가 안되실수도 있으니


jQuery doc를 확인해보면


.hover( handlerIn, handlerOut )


이렇게 되어있습니다.


말그대로 들어올때, 나갈때인거죠 


클릭하기위해서 마우스가 올라왔을때 window.onbeforeunload를 빼버립니다. 그리고 클릭하면서 href가 실행된 후


밖으로 나갈때 다시 원래의 값을 붙여줍니다. 



부족한 글 읽어 주셔서 감사합니다.~




'QA > QA 활동' 카테고리의 다른 글

QA 업무 중 자료 구조?  (0) 2019.01.28
좋은 테스트 코드 및 테스트의 특성  (0) 2018.11.15
Daily note  (0) 2016.09.28
윈도우즈 GPT Convert MBR  (0) 2016.07.05
Back ground 쉘  (0) 2016.06.21

Unicode - 문자 하나당 2바이트의 공간을- 확보

멀티 바이트 : ANSI 에서는 1바이트 공간을 다국어에서는 2바이트의 공간을 확보

영어는 1바이트 한글은 2바이트를 사용 한다.

char , wchar_t ,TCHAR

유니코드상에서 char을 쓰면 문제발생 한문자를 쓰는데 2바이트를 사용하므로

char는 문자 하나당 1바이트 한문자를 쓰지만 실제는 2바이트를 쓰기때문에 글자가 깨져서 나온다.

멀티바이트상에서는 wchar_t 를 사용 할 떄 문제가 발생한다.

wchar_t는 한글자를 쓰는데 2바이트를 사용하므로 영어를 담고있다면

영어는 멀티바이트상에서 1바이트만 표현이 가능하므로 나머지는 0으로 채워진다.

그런데 멀티바이트에서는 NULL 로 인식하기 떄문에 영어 한글자만 출력이 된다.


TCHAR는 멀티바이트상에서는 char로 유니코드상에서는 wchar_t로 바뀐다.

wchar_t를 사용할 경우 앞에 L(매크로)을 붙여준다.


async 파일시스템에 대한 I/O가 비동기적으로 이루어짐

// 비동기 ; 이벤트 큐에 추가된 후 실행이 된다. 

sync 파일 시스템에 대한 I/O가 동기적으로 이루어짐 

// 동기 호출의 끝날때까지 블록 상태를 유지한 후 스레드로 제어가 넘어온다.

메인 이벤트 스레드를 블록하거나 너무 많은 백그라운드 스레드를 실행할 경우 성능의 저하를 가져올 수 있다.  // sync의 경우에는 지속적으로 읽거나 쓰기를 반복할때 최적의 효과를 보여준다.

윈도우즈 특정 버전 이상부터는 MBR 디스크가 아닌 GPT디스크에서 설치가 가능하도록 되어있다.


윈도우즈 인스톨러 중 설치 하기전에 윈도우 복구 창 누르고 -> CMD 명령 프롬포트 혹은


Shift + F10으로 들어갈수 있다.


1. diskpart 입력


2. list disk (디스크 개체 목록 확인)


3. 바꿀 디스크 선택 select disk N


N 디스크가 선택한 디스크입니다.


4. Clean 


5. convert gpt (gpt로 변경) || mbr로 변경시에는 conver mbr


혹시 디스크의 파티션이나 볼륨이 있는 경우는


select disk N 후에 


list volume 하여 select volume N 후에 delete volume 으로 삭제를 진행해 주어야 합니다. 


하핳

**** 추가 사항

// 아 또한 UEFI 모드로 부팅시에는 GPT 디스크에 설치가 되지 않기 때문에 MBR형식으로 바꿔 주어야 한다.


또한 설치할때 2개의 물리적인 HDD 혹은 SSD가 있을때


부트 옵션이 우선권이 있는 곳에만 깔리게 되니

0 SSD

1 HDD 일때


HDD에는 설치가 되지 않기 때문에 깔고 싶을때는 부팅 옵션을


0 HDD

1 SSD 로 바꾸거나


0 SSD의 부팅 에서 disable 혹은 off로 주어놓고 설치후에 다시 On으로하게 되면 된다. 





+ Recent posts