궁극적으로 일관된 서비스에 대한 테스트는 어떻게 작성합니까?


17

궁극적으로 일관된 데이터 저장소 인 Google App Engine Datastore 위에 서비스를 구축하고 있습니다. 내 응용 프로그램의 경우 이것은 괜찮습니다.

그러나 PUT 객체와 GET 객체와 같은 작업을 수행하고 반환 된 객체의 속성을 확인하는 테스트를 개발 중입니다. 불행하게도, 데이터 저장소는 결국 일관성이 있기 때문에 이러한 간단한 테스트는 재현 할 수 없습니다.

궁극적으로 일관된 서비스를 어떻게 테스트합니까?


2
외부 서비스에 대해 재현성을 기대하는 이유는 무엇입니까?

... 그리고 실제로 무엇을 테스트하려고합니까? 코드? 아니면 구글?

5
전체 시스템을 테스트하고 있습니다. 즉, 단위 테스트가 아닌 통합 테스트입니다.
더그 리처드슨

3
How can I reproducibly test an eventually consistent service? -당신은 할 수 없습니다. "복제 적으로"또는 "결국"이라는 단어를 제거해야합니다. 둘 다 가질 수 없습니다.
Robert Harvey

1
재현 가능한지 여부에 관계없이 결국 일관된 결과는 성공적인 결과가 될 것입니다. 이미 앱에 적합하다고 말 했으므로 실제로 테스트하는 것은 무엇입니까? 결국? GAE와의 통합? 코드?
Laiv

답변:


16

기능 테스트를 설계 할 때 비 기능적 요구 사항을 고려하십시오. 서비스에 "x (초 / 분 / 일 등) 내 일관성"이라는 비 기능적 요구 사항이있는 경우 PUT 요청을 실행하고 x를 기다린 다음 GET 요청을 실행하십시오.

이 시점에서 데이터가 아직 도착하지 않았다면 PUT 요청이 요구 사항에 맞지 않는 것으로 간주 할 수 있습니다.


7

테스트가 빠르고 일관되게되기를 원합니다. 최종 일관성으로 인해 때때로 실패 할 수있는 테스트 작성을 시작하면 실패 할 때 테스트를 무시한 다음 어떤 용도로 사용됩니까?

PUT 및 GET 요청을 처리하는 가짜 서비스를 작성하지만 일관성을 유지하기 위해 추가 조작이 있습니다. 테스트는 다음과 같습니다.

datastore.do_put(myobj);
datastore.make_consistent();
validate(datastore.do_get(), myobj);

이를 통해 GET이 PUT 객체를 성공적으로 검색 할 때 소프트웨어의 동작을 테스트 할 수 있습니다. 또한 서비스가 아직 일관성이 없어서 GET이 오브젝트 (또는 올바른 오브젝트)를 찾지 못하면 소프트웨어의 동작을 테스트 할 수 있습니다. 에 전화하지 마십시오 make_consistent().

실제 서비스와 상호 작용하는 테스트는 여전히 가치가 있지만, 100 % 신뢰할 수있는 서비스 (예 : 서비스가 다운 된 경우)가 아니기 때문에 일반 개발 워크 플로우 외부에서 실행해야합니다. 이 테스트는 다음을 위해 사용되어야합니다.

  1. PUT과 후속 GET 사이의 평균 및 최악의 시간에 대한 메트릭을 제공합니다. 과
  2. 가짜 서비스가 실제 서비스와 유사하게 작동하는지 확인하십시오. https://codewithoutrules.com/2016/07/31/verified-fakes/를 참조 하십시오

6

알았어 그래서. "무엇을 테스트하고 있습니까?"가 핵심 질문입니다.

  • Google 물건이 작동한다고 가정 할 때 내부 논리를 테스트하고 있습니다.

이 경우 Google 서비스를 조롱하고 항상 응답을 반환해야합니다.

  • 내 논리가 Google에서 생성하는 일시적 오류에 대처할 수 있는지 테스트 중입니다.

이 경우 Google 서비스를 조롱하고 올바른 응답 전에 항상 일시적 오류를 반환해야합니다

  • 내 제품이 실제 Google 서비스와 실제로 작동하는지 테스트 중입니다.

실제 Google 서비스를 주입하고 테스트를 실행해야합니다. 그러나! 테스트중인 코드에는 일시적 오류 처리 (재시도)가 내장되어 있어야합니다. 따라서 일관된 응답을 받아야합니다. (Google이 매우 잘못 동작하지 않는 한)


Mock 제안에 +1-가능한 경우 추가 옵션에 대해 더 많은 투표를 제공합니다.
mcottle

6

다음 중 하나를 사용하십시오.

  • PUT 후 성공할 때까지 GET을 N 번 다시 시도하십시오. N 시도 후에도 성공하지 못하면 실패합니다.
  • PUT과 GET 사이의 수면

불행히도,이 두 가지 기법 모두 마법의 값 (N 또는 수면 시간)을 선택해야합니다.


1
당신은 분명히 할 수 있습니까 : 이러한 대안입니까, 아니면 보완입니까? 나는 당신이 그것들이 대안이라고 말하는 것을 의미한다고 생각합니다. 그리고 그것이 제가 그들을 생각하는 방식입니다. 하지만 내가 틀렸을 수도 있습니다.
Robin Green

1
맞습니다, 나는 그것들이 대안이라는 것을 의미했습니다.
더그 리처드슨

2

내가 이해하는 것처럼 Google Cloud 데이터 저장소 는 강력하고 일관된 쿼리를 허용합니다 .

단점은 강력하게 일관된 쿼리가 속도가 상당히 제한되어 있다는 것입니다 (테스트 중에 사용할 수있는 것).

테스트 목적으로 강력한 일관성을 가능하게하는 랩퍼 내에서 데이터 스토어에 쿼리배치 할 수 있습니다 .

예를 들어, 메소드를 호출 start_debug_strong_consistency()하고end_debug_strong_consistency() .

start 메소드는 모든 후속 쿼리에 대한 조상 키로 사용할 수있는 키를 작성하고 end 메소드는 키를 삭제합니다.

테스트중인 실제 쿼리에 대한 유일한 변경 사항은 setAncestor(your_debug_key)해당 키가 존재하는 경우 호출 하는 것입니다.


1

이론적으로는 좋지만 항상 실용적이지 않은 한 가지 방법은 테스트중인 시스템의 모든 쓰기 작업을 i 등원 으로 만드는 것 입니다. 즉, 테스트 코드가 고정 된 순서대로 항목을 테스트한다고 가정하면 예상 한 결과를 얻을 때까지 모든 읽기 모든 쓰기를 개별적으로 다시 시도하고 테스트 코드에서 정의한 시간 초과가 초과 될 때까지 다시 시도 할 수 있습니다. 즉, 결과가 B1이 될 때까지 필요한 경우 재 시도하는 A1 작업을 수행 한 다음 결과가 B2가 될 때까지 필요한 경우 재 시도하는 작업 A1을 수행하십시오.

그런 다음 쓰기 작업의 사전 조건을 확인하기 위해 귀찮게 할 필요가 없습니다. 쓰기 작업에서 이미이를 확인하기 때문에 성공할 때까지 다시 시도하기 만하면됩니다!

전체 시스템이 느려지면 증가 할 수있는 동일한 "기본"시간 초과를 최대한 사용하고 특히 느린 작업을 재 시도 할 때 기본값을 개별적으로 무시하십시오.


1

Google App Engine Datastore와 같은 서비스는 여러 POP (전역 확산 지점)에서 데이터 복제를 기반으로합니다. 궁극적으로 일관된 서비스에 대한 통합 테스트는 실제로 해당 POP 세트에 대한 해당 서비스의 복제 속도에 대한 테스트입니다. 복제 방법 및 다양한 인터넷 전송 문제와 같은 여러 가지 요소에 따라 지정된 서비스의 모든 POP로 콘텐츠가 배포되는 속도가 서비스 내의 모든 POP와 동일하지는 않습니다. 이는 두 가지 예입니다. 결국에는 일관된 데이터 저장소 서비스에서 보고서의 대부분을 차지합니다 (적어도 주요 CDN을 작업하는 동안 저의 경험이었습니다).

주어진 플랫폼에서 객체의 복제를 효과적으로 테스트하려면, 각 서비스의 POP에서 최근에 배치 된 동일한 객체를 요청하도록 테스트를 설정해야합니다. POP 목록을 1 ~ 5 회 테스트하거나 POP 목록의 모든 POP에 개체가 있다고보고 할 때까지 제안합니다. 다음은 데이터 스토어에 배치 한 후 1, 5, 60 분, 12 시간, 25 시간 동안 자유롭게 조정할 수있는 테스트를 수행하는 간격 세트입니다. 핵심은 객체를 전체적으로 복제 할 수있는 특정 서비스 기능에 대한 느낌을 얻기 위해 나중에 검토 및 분석을 위해 각 간격마다 결과를 기록하는 것입니다. 데이터 스토어 서비스는 로컬에서 요청한 후에 로컬 복사본을 POP로 가져 오기만합니다. 라우팅은 BGP 프로토콜을 통해 수행됩니다. 따라서 테스트는 특정 POP에 대해 개체가 특정 플랫폼에 대해 전역 적으로 유효하도록 요청해야합니다. . Google 데이터 스토어의 경우 "33 개국 70 개 이상의 존재 지점"에서 지정된 개체를 쿼리하도록 테스트를 설정하려고합니다. Google 지원팀에서 POP 특정 주소 URL 목록을 가져와야 할 수도 있습니다. [ref :https://cloud.google.com/about/locations/ ] 또는 Google이 복제에 빠르게 사용하는 경우 [ https://www.fastly.com/resources ]를 신속하게 지원 합니다.

이 방법의 몇 가지 장점은 다음과 같습니다. 1) 특정 서비스의 복제 플랫폼에 대한 느낌을 얻고, 통합 테스트 중과 마찬가지로 전 세계적으로 그 강도와 약점을 전체적으로 알 수 있습니다. 2) 테스트하는 모든 대상에 대해 컨텐츠를 예열 할 수있는 도구가 제공됩니다 [[해당 로컬 POP에서 사본을 작성하는 첫 번째 요청을 작성하십시오]. 따라서 클라이언트가 요청하기 전에 컨텐츠가 전 세계에 퍼지도록 할 수 있습니다. 지구상의 어느 곳에서나


0

Google App Engine Datastore에 경험이 있습니다. 놀랍게도 로컬에서 실행하는 것은 종종 "일관된"보다 "최종"입니다. 가장 간단한 예 : 새 엔터티를 만든 다음 검색하십시오. 지난 5 년 동안 종종 로컬에서 실행되는 SDK가 새 엔티티를 즉시 찾지 않지만 약 0.5 초 후에 발견하는 것을 보았습니다.

그러나 실제 Google 서버에서 실행하면 그 동작을 보지 못했습니다. 데이터 스토어 클라이언트가 항상 같은 서버에서 실행되도록하므로 일반적으로 변경 사항은 즉시 쿼리에 반영됩니다.

통합 테스트에 대한 조언은 실제 서버에 대해 실행하는 것이므로 결과를 얻기 위해 가짜 폴링이나 지연을 넣을 필요는 없습니다.


편리하지만 통합 테스트에서 여러 응용 프로그램 서버와 관련된 미묘한 손상이 감지되지 않을 수 있습니다. 나는 그들이 좋은 이유 때문에 결국 로컬 서버를 일관성있게 만들었다 고 생각합니다!
Robin Green
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.