RFT + XPATH + 캐시 개체 경로로 UI 개체 식별 효율성 향상

또 긴 밤, 무심한 수면...이번 글은 기술 총결산이지 수상이 아니기 때문에 시작과 따뜻함을 줄이고 본론으로 들어간다.본 문서는 RFT+XPATH를 어떻게 사용하여 자동화 테스트의 집행 효율을 향상시키는지에 대해 새로운 사고방식을 제공했다. 바로 캐시 대상 경로이다. (PS: RFT를 사용하지 않은 학생은 무시할 수 있고 워터로 테스트한 학생도 무시할 수 있다.)
UI 자동화 테스트는 인터페이스 개체 식별 및 유지 보수에 소요되는 비용의 영원한 이슈입니다.
A층의 자동화 테스트를 통해 스크립트의 실행 효율을 높이는 것은 영원한 주제이다. 우리는 반드시 한 차례의 스크립트의 실행 시간을 받아들일 수 있는 범위 내에서 제어해야 한다. 스크립트의 전체적인 실행 시간이 길면 이를 최적화해야 한다. 최적화 방법은 세 가지가 아니다. 첫째, 최적화 용례, 무효 용례의 개수를 줄이는 것이다.2. 스크립트가 UI 대상을 식별하는 효율을 높인다.3. 분포식 집행.본고에서 소개한 방법은 두 번째에 속하여 스크립트 식별 UI 대상의 효율을 높인다

RFT 소개


RFT는 IBM의 자동화 테스트 도구로 QTP와 유사하게 JAVA를 스크립트 언어로 사용하고 ECLIPSE를 IDE로 사용하며 우아하고 강력하다.RFT 식별 대상의 핵심 방법은 RootTestObject의find 방법입니다.우리는 자동화 테스트를 할 때FIND 방법에 대한 봉인을 통해 자신의 대상 식별 구조를 실현했다.하지만find 방법의 집행 효율 문제는 줄곧 나의 마음의 병이다.이전의 상황은 대상을 찾을 때 한 번find 방법을 실행하는 데 적어도 4-6초가 걸린다. 수백 개의 용례를 실행하면 집행 시간을 참을 수 없다. 십여 시간...밤에 스크립트를 보고 아침에 결과를 볼 수 밖에 없다. 오전에 출판될 때 자동화 테스트가 무슨 도움이 될지 기대할 수 없기 때문에 스크립트 집행의 전체 시간을 단축하고 대상의 식별 효율을 높여야 한다.

XPATH 소개


XPATH는 XML의 쿼리 언어입니다.단순하고 효율적입니다.IBM의 개발자 커뮤니티 포럼에서 RFT+XPATH를 어떻게 결합시켜 동적 식별 대상을 실현하는지 전문적인 글이 있는데 매우 훌륭하다.여기에 글의 링크를 제시한다., 저자 유철, 단설비, 형정.감사와 숭배를 표합니다.또한 IBM의 개발자 커뮤니티는 정말 흥미진진하다. 그들의 문서 라이브러리에 있는 자동화 테스트에 관한 글은 모두에게 통독을 권장하고 당신의 이익이 적지 않다는 것을 보증한다. XPATH 식별 대상의 효율은find 방법보다 현저히 우수한데 왜?왜냐하면 XPATH 검색 대상은 특정한 대상을 바탕으로 하는 구체적인 경로이고find 방법은 동적 검색, 즉 전역 검색이다. 이렇게 누적된 대상이 많으면 반드시 느리다.xpath의 예를 들어 아까 그 글에서 유래한 것으로 대상에 대해 XPATH를 사용하여 찾을 때 경로는'org.eclipse.swt.widgets.Shell[@captionText='      'Hello']/org.eclipse.swt.widgets.Button[@text='OK']'), rft의find 방법을 사용하여 같은 효과를 얻으려면atChild로 맞출 수밖에 없습니다. RFT 스크립트를 쓴 학생들은 모두 체득할 수 있을 것입니다. 사실 xpath에서 경로를 사용하지 않고 직접 /: desander[@captionText='Hello']로 전송된다면 그의 실행 효율은find의 전역 검색과 유사합니다.

문제 및 해결 방안


그러나 XPATH는 빠르지만 경로의 유지보수 문제가 단점이다.자동화 테스트 공정에서 우리는 백 개에 가까운 테스트 대상을 사용할 수 있다. 우리는 당연히 모든 대상의 XPATH 경로를 텍스트 파일에 저장할 수 있지만 문제는 프로그램의 페이지 구조가 바뀌면 어떻게 해야 하는가이다. 이렇게 많은 캐시 경로를 바꾸는 것은 장난이 아니라 오류를 정리하는 것도 쉽지 않다는 것이다.그래서 저는 RFT 동적 식별과 XPATH 효율이 빠르다는 두 가지 장점을 결합시키고 유지 보수가 간단하다는 방법을 찾았습니다. 나중에 이런 생각이 들었습니다. 테스트 대상의 부모 대상의class 속성을 순서대로 읽고 이 대상의 경로를 맞추어 캐시 파일에 씁니다. 스크립트가 대상을 식별할 때 먼저 캐시 파일에서 경로를 읽고 XPATH에 전달하여 식별합니다.만약 대상이 식별될 수 있다면 조작을 실행한다.식별이 안 되면find방법을 다시 실행하여 식별하고 식별된 대상의 경로를 캐시 경로로 다시 업데이트한다.find방법도 대상을 찾지 못하면null로 되돌아간다. 이때 인공적으로 검색식별에 개입해야 하는 원인이 된다.이런 방법은 바로 내 제목에서 캐시 대상 경로를 언급한 방법이다. 캐시 파일의 저장 형식에 관해서, 내가 사용하는 정책은 모든 UI 층의 테스트 대상에 유일한 ObjectID를 표식으로 분배하는 것이다.규칙은 스크립트 이름 + Objectid + objecg_value。여기서 Objectid 및 Objectvalue는 테스트 대상을 식별할 때 사용하는 속성입니다.RFT 스크립트를 쓴 친구들은 다 아실 거예요. 모르는 분들은 저에게 사적인 편지를 보내주세요. 한 마디로 설명할 수 있는 것도 아니니까요. 이것은 교과서가 아니니까 양해해 주세요. 객체 경로를 캐시하는 방법의 핵심은 다음과 같습니다. 1. 테스트 대상을 식별할 때 영원히 캐시 파일에서 대상 경로를 읽고 XPATH로 식별한다. 2. 경로가 효력을 상실하거나 존재하지 않을 때 자동화 테스트 코드가 자동으로 경로를 업데이트한다. 그렇지 않으면 XPATH 경로를 직접 쓰고 싶은 학생은 먼저 잘 고려하는 것이 좋다. 다음은 몇 가지 핵심 코드의 실현으로 여러분들이 참고하시기 바랍니다.(PS: 코드를 직접 복사하려는 학생은 아래의 내용을 무시할 수 있습니다. 왜냐하면 당신은 이 코드의 밑바닥 지원 코드가 없기 때문에 복사해도 소용없습니다.) 객체 경로를 반복적으로 읽는 방법: private void addPropertyToCatch(TestObject to, StringBuffer str) { Hashtable<Object, Object> p = to.getProperties(); String _class = p.get(".class").toString(); str.append("child::").append(_class); if (_class.contains("Html.TR")) { int rowIndex = this.getHtmlTRIndex(to); str.append("[").append(rowIndex + 1).append("]_@/@"); } else if (_class.contains("Html.TD")) { //IE의 문서 모델에서 모든 인덱스는 1에서 시작합니다 int index = this.getHtmlTDIndex(to); str.append("[").append(index + 1).append("]_@/@"); } else { int classIndex = this.getHtmlTOIndex(to); if (classIndex == -1) { if (_class.contains("Html.HtmlDocument") && p.containsKey(".title")) { String title = p.get(".title").toString(); str.append("[contains(@_").append(".title,'").append(title) .append("')]"); } str.append("_@/@"); } else { str.append("[").append(classIndex + 1).append("]").append( "_@/@"); } } } 이 방법으로 xpath를 가져오려면TestObject 대상을 전송할 수 있습니다.주의해야 할 것은 스크립트를 통해 읽은 TD, TR기classIndex는 0에서 시작하지만, IE와 XPATH에서 모든 요소의 위치는 1에서 시작한다는 점이다. public String getTestObjectTreeStr(TestObject to, String id, String value) { if(to == null){ return "null"; } StringBuffer xpath = new StringBuffer(); addPropertyToCatch(to, id, value, xpath); this.getTestObjectProperty(to, xpath); String path = xpath.toString(); String rs = parseXpath(path); return rs += "[1]"; } 객체의 XPATH 경로를 가져오면 다음과 같이 객체 경로 문자열을 캐시 파일에 쓸 수 있습니다. public void writeXpathToFile1(String ObjectID, String xpath, String filename) { File file = new File(filename); try { if (this.isObjectXpathExists(ObjectID, file)) { this.updataXpathbyObjectID(ObjectID, xpath, filename); } else { BufferedWriter writer = new BufferedWriter(new FileWriter(file, true)); writer.write(ObjectID + "=" + xpath); writer.write("\r"); writer.flush(); writer.close(); } } catch (IOException e) { e.printStackTrace(); } String rootStr = this.getFirstRootStr(xpath); String rootStr_ID = ObjectID + "_head"; try { if (this.isObjectXpathExists(rootStr_ID, file)) { return; } else { BufferedWriter writer = new BufferedWriter(new FileWriter(file, true)); writer.write(rootStr_ID + "=" + rootStr); writer.write("\r"); writer.flush(); writer.close(); } } catch (IOException e) { e.printStackTrace(); } file = null; } 우리는 페이지 구조나 대상 속성이 변화하는 상황을 고려해야 하기 때문에 캐시 파일의 xpath 경로를 자동으로 업데이트하는 방법을 써야 한다.사실 업데이트된 XPATH 경로를 읽어서 원래 경로를 덮어쓰는 거예요. public void updataXpathbyObjectID(String objectID,String xpath,String filename){ ArrayList<String> list = new ArrayList<String>(); StringBuffer sb = new StringBuffer(); File file = new File(filename); BufferedReader in = null; BufferedWriter ut = null; try { in = new BufferedReader(new FileReader(file)); String temp = ""; while((temp = in.readLine()) != null){ list.add(temp); } // 찾기 및 삭제 for(int i = 0; i < list.size(); i++){ if(list.get(i).contains(objectID + "=")){ sb.append(objectID + "=").append(xpath).append("\r"); }else{ sb.append(list.get(i)).append("\r"); } } out = new BufferedWriter(new FileWriter(file)); out.write(sb.toString()); out.flush(); out.close(); out = null; in.close(); in = null; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } 마지막으로 캐시를 사용하여 대상을 찾는 것은 매우 간단하다.어떤 방법으로 대상을 얻었든지 간에 코드를 호출하기 전에 캐시 대상을 먼저 호출하는 방법은 다음과 같다. String xpath = this.getObjectCachePath(ObjectID, filename); to = GuiTestObjectFactory.getObjectByXPathAndWaitTime(rootGuiTestObject, xpath, 5); if(to==null) {// 캐시 파일의 경로에 따라 대상을 식별할 수 없으면find 방법으로 스크립트의 건장성을 확보하는 것이 중요합니다 RootTestObject root = this.getRootTestObject(); TestObject[] to = root.find(atDescant(".text","useName)); return to[0]; } 캐시 대상 경로의 방법은 현재 나와 나의 동료가 각자 맡은 자동화 테스트 프로젝트에서 각각 사용하는데 효과는 그런대로 괜찮다. 자동화 테스트의 집행 효율이 현저히 높아졌다. 나의 스크립트를 예로 들면 원래 모든 스크립트를 집행하는 데 14시간이 걸렸는데 이 방법을 사용한 후 집행 시간을 8시간으로 단축시켰지만 집행 성공률이 떨어졌다.원래 92%에서 75%까지 떨어졌는데... 이유가 뭘까요?스크립트가 너무 빨리 실행돼서!원래find방법은 한 번에 적어도 몇 초의 시간이 걸렸지만, 지금은 한 대상을 식별하는 데 가장 빠르면 몇 백 밀리초밖에 걸리지 않기 때문에 많은 건장성 문제가 드러난다.지금 저는 일주일의 시간을 들여 끊임없이 보완을 해서 현재 87%의 통과율(물론 절차적 결함도 있습니다)을 얻었습니다. 그래서 만약에 이 방법으로 자신의 각본을 보완하기 시작하고 싶다면 마음의 준비를 하세요. 물론 상급자와 먼저 소통을 해야 합니다. 그렇지 않으면 한두 주일 동안 부딪혀 들어가지만 그는 업무가 나오는 것을 보지 못할 것입니다. 그러면...뒤에 아시겠죠. 여기에서 제 방법은 기본적으로 소개가 끝났습니다. 본고에서 말한 방법은 최적화 방법 중의 하나일 뿐입니다. 스크립트의 식별 효율을 높이는 방법은 사실 여러 가지가 있습니다. 예를 들어 IE의 프로세스에 직접 주입하여 그document을 얻고 JS로 IE의 요소를 조작하는 것입니다. 이 방법은 정말 가능하지만 난이도도 있습니다.흥미가 있는 학생은 한번 해 볼 수 있다.본고에서 열거한 코드를 복사하면 사용할 수 없습니다. 왜냐하면 많은 밑바닥의 코드가 붙일 수 없기 때문에 여러분들은 코드를 참고하여 사고방식을 이해하세요. 사고방식은 코드보다 영원히 중요합니다.다음 단계에 나는 이 부분의 코드를 JAR 가방으로 다시 써서 발표할 것이니, 그때 모두가 사용하기에 편리할 것이다. 마지막으로 포토샵을 해 주세요. 왜 FIREBUG 플러그인을 사용하지 않고 XPATH 경로를 직접 가져오는지 절대 묻지 마세요. 프로그램이 FIREFOX를 지원하지 않기 때문에 대답이 끝났습니다.

좋은 웹페이지 즐겨찾기