반응형

제목: 언어 교차적인 미들웨어 기능 테스팅(Cross-Language Functional Testing for Middleware)

저자: A. Puder 1, 미국

문서유형: 학계 페이퍼( 13페이지)

 

Java로 작성된 미들웨어 API 기능 테스트를 타 프로그래밍 언어로 자동 생성하는 프레임워크를 제안한 자료



미들웨어(Middleware)

  • 미들웨어는 특정 플랫폼이나 언어에 독립적인 분산 애플리케이션 개발을 허용함
  • 미들웨어 기술의 정확한 동작을 보장하기 위한 테스트 케이스 생성 노력들이 이루어짐 예) CORVAL(CORBA Validation), COST(CORBA Open Source Testing), WS-I(Web Services Interoperability)
  • 미들웨어 기능 테스팅의 어려움 중 하나는 미들웨어 플랫폼이 본질적으로 여러 프로그래밍 언어를 지원하는 이질성(heterogeneity)을 가진다는 점이다. , 여러 다른 프로그래밍 언어를 위한 미들웨어 API가 존재하며, 이는 미들웨어 플랫폼의 기능성(functionality)을 테스트하기 위해 작성한 기능 테스트를 해당 미들웨어가 지원하는 모든 언어로 재작성 할 필요가 있음을 의미한다.
  • 이렇게 여러 언어에 대해 동일한 기능 테스트가 재작성되는 작업은 중복이 심하고 그 과정에서 에러가 유입될 가능성도 높다. 예를 들면, COST100,000 라인의 기능 테스트 코드 중에서 약 절반이 C++ API를 테스트하고 나머지 절반은 Java API를 테스트 한다(, 모든 테스트에 대해 C++Java의 두 개의 다른 구현이 존재함)
  • 본 논문은 Java로 작성된 기능 테스트를 기반으로 다른 프로그래밍 언어를 위한 동일한 테스트를 자동으로 도출하는 프레임워크를 제안(, 타 언어로의 테스트 코드 자동 변환을 통해 수작업을 줄이고 에러 가능성도 줄이고자 함)


미들웨어의 기능 테스팅(Functional Testing)

아래는 두 개의 다른 미들웨어 기술인 CORBA Web Services의 기능 테스팅 예를 통해 같은 일을 하는 기능 테스트 코드가 여러 번 복제(replication)되어야 하는 문제를 설명함


1. CORBA 기능 테스팅 예

  • CORBA(Common Object Request Broker Architecture)는 객체 지향 애플리케이션을 위한 플랫폼 독립적인 미들웨어 아키텍쳐를 정의함
  • OMG가 표준화한 CORBA의 핵심 명세서는 1000 페이지가 넘는 양으로 수백 개의 API 기능을 가짐. 이 기능들을 테스트 하기 위해 작성된 기능 테스트는 CORBA가 지원하는 모든 언어로 번역될 필요가 있음
  • COST 프로젝트의 실제 기능 테스트에서 발췌한 아래의 Java 코드는 DynamicAny에 대한 테스트이다(JUnit을 사용하여 구현됨). DynamicAny는 단일 데이터 항목을 위한 범용적 컨테이너(a generic container)이며, DynamicAny에 담길 수 있는 데이터 항목의 타입은 DynamicAny가 생성될 때 결정됨(라인 J18 J19). DynamicAny는 모든 타입의 CORBA-IDL을 지원함. 아래 예는 먼저 값이 700long 데이터를 DynamicAny에 넣고(라인 J20), DynamicAny에 있는 값을 추출하고(라인 J21), 컨테이너에 넣은 값과 빼낸 값이 동일한지 확인하기 위해 이 둘을 비교하는(라인 22) 간단한 기능 테스트이다.

  • 아래 코드는 위와 동일한 기능 테스트를 C++로 작성한 예이다(CORBAC++ API와 테스트 프레임워크로 CPPUnit을 사용한 점을 제외하고 개념적으로 Java 버전과 동일)


2.  Web Services 기능 테스팅 예

  • Web Services는 개념적으로 CORBA와 동일하지만 Microsoft의 강한 지원을 받으며 유망 기술로 떠오름
  • XML이 많은 Web Services 표준의 기초 토대로 사용되며, 표준화 단체인 WS-I Web Services의 범위를 정의한 ‘basic profile’이라 불리는 표준을 공표함
  • Web Services는 이식성(portability)을 지원하지 않음. , 특정 프로그래밍 언어를 위한 API가 서로 다른 Web Services 제품 간에 크게 다를 수 있음(아래 예 참조)
  • 아래 코드는 SunWeb Services SDK를 사용한 간단한 은행 계정 인터페이스의 서버 쪽 매핑을 보여줌. SunWeb Services 표준 구현에서는 서버 측이 Remote 인터페이스를 확장하는 Java 인터페이스를 구현해야 하며, 이 인터페이스에 속하는 모든 메쏘드는 반드시 RemoteExceptionthrow 해야 함


  • 아래는 위와 동일한 것을 BEAWebLogic Server로 구현한 예이다. BEAcom.bea.jws.WebService로부터 도출된 Java 클래스로 은행 계정 인터페이스를 구현하며, 모든 원격 메쏘드(remote methods)는 특수한 JavaDoc 코멘트인 @common:operation을 통해 표시된다.

  • 모든 경우에 하나의 언어(Java)가 사용되었다 하더라도 이식성의 결여로 인해 각 Web Service 제품 마다 기능 테스트가 재작성 되어야만 하므로 Web Services를 위한 기능 테스팅은 CORBA보다 더 까다롭다



제안 프레임워크

  • 미들웨어의 기능 테스트를 단 한번만 작성하고 이를 기반으로 미들웨어가 지원하는 타 언어의 기능 테스트를 자동 생성하는 것이 목표
  • 제안 프레임워크에서는 기능 테스트가 일단 Java로 작성되고, 이 기능 테스트의 컴파일된 버전을 가진 Java Class FileXML 기반 프로그래밍 언어인 XMLVM로 자동 변환된다. XMLVM 프로그램은 타겟 프로그래밍 언어(, C++)로의 API 변환을 거치고, 이어서 XSL-변환을 통해 타겟 언어로 쓰인 기능 테스트가 자동 도출된다.

[제안 프레임워크의 언어 매핑 프로세스]


Java 가상 머신(Virtual Machine)

제안된 프레임워크의 핵심인 XMLVMJava 가상 머신(VM)에 의해 실행되는 바이트 코드를 모델로 하므로 이 VM 개념에 대한 이해가 필요하다.

  • Java 컴파일러는 Java 소스 코드를 하드웨어에 독립적인 바이트 코드(Class File에 저장됨)로 변환한다. 바이트 코드는 타 하드웨어 아키텍쳐의 머신 코드와 유사함
  • 아래 그림처럼 Java 가상 머신은 간단한 스택 기반 머신을 구현한다. Class File로의 인스트럭션 포인터(실행될 다음 인스트럭션을 가리킴)를 유지하며, 일단 메쏘드에 진입하면 스택과 지역 변수로 구성된 새로운 프레임이 생성된다. 이 프레임은 메쏘드에서 빠져 나오자마자 삭제됨
  • Java VM은 현 프레임(most nested 메쏘드 호출)으로의 포인터를 유지한다. 메쏘드는 자기 자신의 스택과 지역 변수로만 액세스 하고, 메쏘드의 실제 패러미터는 자동으로 지역 변수에 저장된다.
  • Java VM은 스택 프레임 외에도 가비지 컬렉션된 힙(garbage collected heap)을 유지한다(여기에 프로그램이 새로운 오브젝트를 할당할 수 있음).
  • Java 바이트 코드에는 iadd(스택으로부터 두 개 정수를 불러내어 그 합을 다시 스택에 넣음) 같은 단순한 저레벨 인스트럭션과 new(새로운 오브젝트를 인스턴스화)invokevirtual(버츄얼 메쏘드를 호출) 같은 고레벨 인스트럭션이 혼재함

[Java 가상 머신]


제안 프레임워크의 매핑 프로세스

1) XMLVM 생성

  • XMLVM은 사람(프로그래머)이 직접 읽고 쓰는 것이 목적이 아닌 XML 기반 저레벨 언어이다(Java VM의 바이트 코드와 밀접하게 관련되어 있어서 이름을 XMLVM이라 함).
  • XMLVM의 구문(syntax)Java 바이트 코드 인스트럭션과 매우 유사하므로 Java Class File XMLVM 간의 직접적인 양방향 매핑이 존재함
  • 기능 테스트를 직접 XMLVM로 작성하는 것이 아니라 프로그래머가 Java로 작성한 프로그램의 Class File로부터 XMLVM 프로그램이 자동 생성됨(도구 사용)
  • XMLVM 스키마를 따르는 아래 XML은 앞에 나온 DynamicAnyJava 기능 테스트를 자동 변환한 예이다. 라인 X3Java 프로그램의 라인 J2에 있는 클래스 선언, X5J4에 있는 인스턴스 멤버 orb, X8 J9에 있는 testAccessBasicValue() 메쏘드 선언에 매핑됨. X9의 애트리뷰트 stacklocals은 스택의 크기와 이 메쏘드를 위해 필요한 지역 변수 수를 기술함(Java 컴파일러는 플로우 분석을 통해 이 정보를 계산). 라인 X10~X12signatureX13~X28testAccessBasicValue()의 구현을 나타낸다.


  • 라인 X15~X26 Java 컴파일러에 의해 생성된 바이트 코드(Java 프로그램의 라인 J18에 있는 소스 코드의 컴파일된 버전을 나타냄). 4개의 바이트 코드 인스트럭션이 포함됨
    - X15의 <getfield>는 인스턴스 멤버 orb의 값을 스택에 밀어 넣음
    - X17의 <getstatic>은 정적 변수 org.omg.CORBA.TCKind.tk_long의 값을 스택에 밀어 넣음
    - X19의 <invokevirtual>는 버츄얼 메쏘드 get_primitive_tc()를 호출함
    - X26의 <astore>는 스택에서 결과를 불러내어 지역 변수에 저장함


2) API 변형(transformation)

  • 자동 생성된 XMLVM 프로그램은 소스 코드의 API를 타겟 언어에서 가용한 API로 적응시키는 API 변형 과정을 거친다. , 원래의 테스트 케이스가 Java-CORBAJUnit 같은 특수한 API를 사용하여 작성되어 있으므로 XSL-stylesheet를 적용하여 개명(renaming)하거나 또는 의미상(semantically) 동등한 버전으로 바꾸는 작업이 수행됨
  • 타겟 언어가 C++인 경우의 API 변형 예를 들자면
    - JUnit
    에서 CPPUnit로 변형: 라인 J2의 베이스 클래스 junit.framework.TestCase를 라인 C2CppUnit.TestCase로 변경, J22assertEquals()C23CPPUNIT_ASSERT_EQUAL_MESSAGE()로 변경
    - Java
    를 위한 CORBA에서 C++을 위한 것으로 변형: 라인 J4의 네임스페이스 프리픽스 omg.org.CORBA를 라인 C4CORBA로 변경, J18의 메쏘드 get_primitive_tc()C19_duplicate()로 변경
  • XSL-stylesheet를 통한 API 변형의 결과는 여전히 XMLVM 프로그램이다(XMLVMAPI로 표기됨). 아래는 TypeCode를 생성하는 XMLVM 코드(라인 X15~X26) API 변형을 수행한 결과이다. get_primitive_tc()를 통해 TypeCode를 생성하기 위해 ORB-singleton을 사용하는 대신에 여기서는 CORBA를 준수하는 모든 C++ ORB가 가져야 하는 상수인 _tc_long을 중복(duplicating)하여 TypeCode를 생성한다


3) 언어 변형(Language transformation)

  • API 변형의 결과로 나온 XMLVMAPI는 또 다른 XSL-stylesheet에 의해 타겟 언어로 변환됨. 원래 Java 프로그램의 역공학(또는 디컴파일) 시도 없이 XMLVM 인스트럭션을 일대일로 타겟 언어로 매핑함
  • 아래는 오브젝트 리퍼런스를 스택으로부터 불러와 지역 변수에 저장하는 XMLVM 인스트럭션인 <astore>C++ 코드를 생성하는 XSL-템플리트이다. 일례로 라인 A10 <astore>을 이를 통해 C++로 변환시키면 locals[3] = stack.pop(); 이 생성됨

  • 아래는 A1~A10에 보여진 XMLVM 프로그램의 C++ 버전을 나타낸다. 라인 T12 T13에 위치한 두 개 클래스(XMLVM::Locals, XMLVM::Stack)를 통해 Java VM을 흉내 낸다. 이 두 C++ 클래스는 C++를 위한 XMLVM 라이브러리의 일부이며, 클래스 XMLVM::Stackpush pop 같은 공통적인 스택 오퍼레이션을 지원한다. 두 클래스 모두 Java VM에 의해 일반적으로 수행되는 garbage collection을 구현한다. 변수 op1op2(라인 T14, T15)는 일부 XMLVM 인스트럭션이 필요로 하는 임시 변수로 사용됨


제안 프레임워크의 제약

  • DynamicAny 처럼 모든 언어에 존재하는 공통 API도 있지만 특정 언어에 고유한 API도 존재함. 제안된 프레임워크가 공통 API에 대해서는 잘 작동하지만 언어 고유의 API에는 제약을 가진다.
  • 예를 들어, CORBA C++ 언어 매핑이 C++ 포인터를 위하여 다양한 helper 타입을 정의하지만 C++ 포인터가 Java 오브젝트 참조(object references) 보다 훨씬 복잡하므로 이런 helper 타입들이 Java에는 존재하지 않음. 따라서 이 helper 타입들의 정확성을 테스트 하는 것이 목적인 기능 테스트는 수작업을 통해 C++로 작성될 필요가 있게 된다.


반응형

+ Recent posts