2010-01-07 4 views
25

우리는 객체에 대해 잠재적으로 장기 실행 계산을 수행하는 비동기 태스크를 가지고 있습니다. 그런 다음 결과가 개체에 캐시됩니다. 여러 작업이 동일한 작업을 반복하지 않도록하기 위해 원자 적 SQL 업데이트로 잠금을 추가했습니다.RSpec 단위 테스트의 경쟁 조건 시뮬레이션

UPDATE objects SET locked = 1 WHERE id = 1234 AND locked = 0 

잠금은 비동기 작업에만 적용됩니다. 개체 자체는 여전히 사용자가 업데이트 할 수 있습니다. 이런 경우 이전 버전의 객체에 대한 완료되지 않은 작업은 결과가 유효하지 않을 수 있으므로 결과를 폐기해야합니다. 이것은 또한 원자 SQL 업데이트와는 꽤 쉽게 : 객체가 업데이트되었습니다

UPDATE objects SET results = '...' WHERE id = 1234 AND version = 1 

경우, 그 버전이 일치하지 않습니다 그래서 결과가 삭제됩니다.

이러한 두 개의 원자 적 업데이트는 가능한 모든 경쟁 조건을 처리해야합니다. 문제는 단위 테스트에서 그것을 확인하는 방법입니다.

첫 번째 세마포는 테스트가 쉽습니다. 두 가지 가능한 시나리오, 즉 (1) 개체가 잠긴 위치와 (2) 개체가 잠겨 있지 않은 위치의 두 가지 테스트를 설정하는 것만 큼 쉽습니다. (우리는 SQL 쿼리의 원 자성을 데이터베이스 공급 업체의 책임으로 테스트 할 필요가 없습니다.)

두 번째 세마포는 어떻게 테스트합니까? 객체는 첫 번째 세마포어 이후 몇 번째 시간이지만 두 번째 전에 변경되어야합니다. 이렇게하면 업데이트가 안정적이고 일관되게 수행 될 수 있도록 실행이 일시 중지되어야하지만 RSpec을 사용하여 중단 점을 주입하는 것은 지원되지 않습니다. 이것을 할 수있는 방법이 있습니까? 또는 그러한 경쟁 조건을 시뮬레이션하기 위해 간과할만한 다른 기술이 있습니까?

답변

26

전자 제품 제조 아이디어를 빌려 테스트 코드를 직접 생산 코드에 넣을 수 있습니다. 테스트 장비가 회로를 제어하고 프로빙 할 수있는 특수 장소가있는 회로 보드를 제작할 수있는 것처럼 코드와 동일한 작업을 수행 할 수 있습니다.

우리가 데이터베이스에 행을 삽입하는 몇 가지 코드가 있다고 가정

class TestSubject 

    def insert_unless_exists 
    if !row_exists? 
     insert_row 
    end 
    end 

end 

을하지만이 코드는 여러 컴퓨터에서 실행되고 있습니다. 다른 프로세스가 우리 테스트와 삽입 사이에 행을 삽입하여 DuplicateKey 예외를 발생시킬 수 있기 때문에 경쟁 조건이 있습니다. 우리는이 코드가 해당 경쟁 조건에서 발생하는 예외를 처리하는지 테스트하려고합니다. 이를 수행하려면 row_exists?을 호출 한 후 행을 삽입하고 insert_row을 호출하기 전에 행을 삽입해야합니다. 그래서 바로 거기에 테스트 훅을 추가해 보겠습니다. 야생에서 실행될 때 약간의 CPU 시간을 먹는 것을 제외하고는 후크는 아무 것도하지 않습니다. 코드가 경쟁 조건에 대한 테스트중인 때, 테스트 원숭이 패치 before_insert_row_hook :

class TestSubject 
    def before_insert_row_hook 
    insert_row 
    end 
end 

는 교활한 아닌가? 무심코 애벌레의 몸을 납치 한 기생 말벌 유충과 같이이 테스트는 테스트중인 코드를 납치하여 테스트해야하는 정확한 조건을 만들어냅니다.

이 아이디어는 XOR 커서만큼 간단하므로 많은 프로그래머가 독자적으로 발명 한 것으로 생각됩니다. 경쟁 조건이있는 코드를 테스트하는 것이 일반적으로 유용하다는 것을 알았습니다. 나는 그것이 도움이되기를 바랍니다.

+1

A-ha. 그렇게 할 것입니다.명시 적 후크를 추가하는 대신, 나는 단지'alias_method_chain'을 사용하여 두 개의 세마포어 사이에서 호출되는 메소드의 기능을 확장 할 수 있습니다. 장기 실행 태스크. – Ian

+0

이안, 그럴거야. –

+4

+1 당신의 직유에 기생 말벌 유충을 사용합니다. – aronchick

관련 문제