테스트 - 제출 - 복원: Ruby에서 유효한 코드 워크플로우 테스트

21852 단어 ruby
본고는 최초로 José M. GilgadoHoneybadger Developer Blog에 저술되었다.
이것은 우리 모두에게 발생했다.소프트웨어 프로젝트가 성장함에 따라 일부 코드 라이브러리는 최종적으로 생산에 들어갔고 전면적인 테스트 세트는 하나도 없었다.몇 달 후에 같은 분야의 코드를 다시 볼 때 이해하기 어려울 수도 있습니다.더 심각한 것은 버그가 있을지도 모른다는 것이다. 우리는 어디서부터 그것을 복구해야 할지 모른다.
테스트가 없는 상황에서 코드를 수정하는 것은 중대한 도전이다.우리는 이 과정에서 어떤 것도 파괴할지 확정할 수 없고, 모든 일을 수동으로 검사하는 것도 고작 실수하기 쉽다.통상적으로 이것은 불가능하다.
이런 코드를 처리하는 것은 우리가 개발자로서 수행하는 가장 흔히 볼 수 있는 임무 중의 하나이다. 여러 해 동안 많은 기술들이 이 문제를 주목했다. 예를 들어 characterization tests이다. 우리는 이전 글에서 이 점을 토론했다.
오늘 우리는 또 다른 특징 테스트를 바탕으로 하는 기술을 소개할 것이다. 이 기술은 Kent Beck이 도입했고 그는 여러 해 전에 TDD를 현대 프로그래밍 세계에 도입했다.

TCR이란 무엇입니까?


TCR은'test,commit,revert'를 대표하지만 더 정확한 말은'test&commit | | revert'입니다.왜 그런지 봅시다.
이 기술은 남겨진 코드를 테스트하는 작업 흐름을 묘사했다.프로젝트 파일을 저장할 때마다 테스트를 실행하는 스크립트를 사용할 것입니다.절차는 다음과 같습니다.
  • 우선, 우리는 테스트할 유류 코드 부분을 위해 빈 단원 테스트를 만듭니다.
  • 그리고 우리는 자산을 추가하고 테스트를 보존합니다.
  • 은 스크립트를 설정했기 때문에 테스트가 자동으로 실행됩니다.성공하면 변경 사항이 커밋됩니다.실패하면 변경 사항이 삭제(복원)됩니다. 다시 시도해야 합니다.
  • 일단 테스트가 통과되면 우리는 새로운 테스트 용례를 추가할 수 있다.
    본질적으로 TCR은 코드를'녹색'상태로 유지하는 것이지, 우리가 테스트 드라이브 개발에서 한 것처럼 실패한 테스트 (빨간색) 를 작성한 다음 (녹색) 를 통과하는 것이 아니다.만약 우리가 실패한 테스트를 작성한다면, 그것은 사라지고, 우리는 다시 녹색 상태로 돌아갈 것이다.

    의도


    이런 기술의 주요 목표는 매번 테스트 용례를 추가할 때마다 코드를 더욱 잘 이해하는 것이다.이것은 자연스레 테스트 커버율을 증가시키고 많은 재구성 장애를 없앨 것이다. 그렇지 않으면 이런 재구성은 불가능하다.
    TCR의 장점 중 하나는 여러 장면에서 유용하다는 것이다.우리는 그것을 테스트가 전혀 없는 코드나 일부 테스트 코드에 사용할 수 있다.만약 테스트가 통과되지 않았다면, 우리는 변경 사항을 복구하고 다시 시도하기만 하면 된다.

    우리는 그것을 어떻게 사용합니까?


    Kent Beck은 다른 글과 동영상(마지막 링크)에서 프로젝트의 일부 파일을 저장한 후 실행하는 스크립트를 사용하는 것이 좋다고 지적했다.
    이것은 어느 정도에 당신이 테스트를 시도한 항목에 달려 있습니다.다음 스크립트와 유사한 내용은 편집기의 플러그인을 사용하여 파일을 저장할 때마다 실행되는 좋은 시작입니다.
    (rspec && git commit -am "WIP") || git reset --hard
    
    Visual Studio 코드를 사용하는 경우 저장할 때마다 "runonsave" 플러그인을 실행할 수 있습니다.항목에 위 명령 또는 유사한 명령을 포함할 수 있습니다.이 경우 전체 프로필은
    {
      "folders": [{ "path": "." }],
      "settings": {
        "emeraldwalk.runonsave": {
          "commands": [
            {
              "match": "*.rb",
              "cmd": "cd ${workspaceRoot} && rspec && git commit -am WIP || git reset --hard"
            }
          ]
        }
      }
    }
    
    나중에 Github를 사용하면 명령줄에서 Git 압축 커밋을 직접 사용하거나 PR 병합 시 Github를 사용할 수 있습니다.
    .
    이것은 우리가 처리하고 있는 지점에서 하는 모든 제출에 대해 우리는 주 지점에서 하나의 제출만 받을 수 있다는 것을 의미한다.Github의 이 그림은 이 점을 잘 설명한다.
    .

    첫 번째 테스트를 TCR로 작성합니다.


    우리는 간단한 예시를 사용하여 이 기술을 설명할 것이다.우리는 어떤 종류가 일하고 있다는 것을 알고 있지만, 우리는 그것을 수정해야 한다.
    우리는 변경을 진행하고 배치할 수 있다.그러나 우리는 이 과정에서 어떤 것도 파괴하지 않기를 바란다. 이것은 항상 좋은 생각이다.
    # worker.rb
    class Worker
      def initialize(age, active_years, veteran)
        @age = age
        @active_years = active_years
        @veteran = veteran
      end
    
      def can_retire?
        return true if @age >= 67
        return true if @active_years >= 30
        return true if @age >= 60 && @active_years >= 25
        return true if @veteran && @active_years > 25
    
        false
      end
    end
    
    첫 번째 단계는 우리가 거기에 그것들을 추가할 수 있도록 새 파일을 만드는 것이다.저희가 can_retire? 방법에서 첫 번째 줄을 봤어요.
      def can_retire?
        return true if @age >= 67
        ...
        ...
      end
    
    따라서 이 사례를 먼저 테스트할 수 있습니다.
    # specs/worker_spec.rb
    require_relative './../worker'
    
    describe Worker do
      describe 'can_retire?' do
        it "should return true if age is higher than 67" do
    
        end
      end
    end
    
    TCR을 사용할 때 저장할 때마다 테스트가 통과되지 않으면 최신 변경 사항이 사라진다는 빠른 알림이 있습니다.따라서 우리는 단언이 있는 한 줄이나 여러 줄 코드를 실제로 작성하고 저장하기 전에 가능한 한 많은 코드를 가지고'설정'테스트를 하기를 희망한다.
    만약 우리가 이렇게 상술한 파일을 저장한다면, 우리는 테스트를 위해 한 줄을 추가할 수 있다.
    require_relative './../worker'
    
    describe Worker do
      describe 'can_retire?' do
        it "should return true if age is higher than 67" do
          expect(Worker.new(70, 10, false).can_retire?).to be_true ## This line can disappear when we save now
        end
      end
    end
    
    우리가 돈을 저축할 때, 만약 새 선이 사라지지 않았다면, 우리는 매우 잘했다.테스트 통과!

    추가 테스트 추가


    일단 우리가 첫 번째 테스트를 진행하면, 우리는 계속해서 더 많은 사례를 추가할 수 있으며, 동시에 오류 사례를 고려할 수 있다.몇 가지 일을 거쳐 우리는 이러한 결과를 얻었다.
    # frozen_string_literal: true
    
    require_relative './../worker'
    
    describe Worker do
      describe 'can_retire?' do
        it 'should return true if age is higher than 67' do
          expect(Worker.new(70, 10, false).can_retire?).to be true
        end
    
        it 'should return true if age is 67' do
          expect(Worker.new(67, 10, false).can_retire?).to be true
        end
    
        it 'should return true if age is less than 67' do
          expect(Worker.new(50, 10, false).can_retire?).to be false
        end
    
        it 'should return true if active years is higher than 30' do
          expect(Worker.new(60, 31, false).can_retire?).to be true
        end
    
        it 'should return true if active years is 30' do
          expect(Worker.new(60, 30, false).can_retire?).to be true
        end
      end
    end
    
    모든 상황에서 우리는 먼저 "it"블록을 작성하고 저장한 다음에 expect(...)으로 단언을 추가합니다.
    여느 때와 마찬가지로 우리는 가능한 한 많은 테스트를 추가할 수 있지만, 모든 내용이 덮어썼다는 것을 상대적으로 확인한 후에 너무 많은 테스트를 추가하는 것을 피하는 것은 의미가 있다.
    일부 사례는 포괄해야 하기 때문에 우리는 그것들을 추가하여 완전성을 확보해야 한다.

    최종 테스트


    이것은 최종 형식의 규범 문건이다.보시다시피 우리는 여전히 더 많은 사례를 추가할 수 있지만, 나는 이것이 TCR의 과정을 설명하기에 충분하다고 생각한다.
    # frozen_string_literal: true
    
    require_relative './../worker'
    
    describe Worker do
      describe 'can_retire?' do
        it 'should return true if age is higher than 67' do
          expect(Worker.new(70, 10, false).can_retire?).to be true
        end
    
        it 'should return true if age is 67' do
          expect(Worker.new(67, 10, false).can_retire?).to be true
        end
    
        it 'should return true if age is less than 67' do
          expect(Worker.new(50, 10, false).can_retire?).to be false
        end
    
        it 'should return true if active years is higher than 30' do
          expect(Worker.new(60, 31, false).can_retire?).to be true
        end
    
        it 'should return true if active years is 30' do
          expect(Worker.new(20, 30, false).can_retire?).to be true
        end
    
        it 'should return true if age is higher than 60 and active years is higher than 25' do
          expect(Worker.new(60, 30, false).can_retire?).to be true
        end
    
        it 'should return true if age is higher than 60 and active years is higher than 25' do
          expect(Worker.new(61, 30, false).can_retire?).to be true
        end
    
        it 'should return true if age is 60 and active years is higher than 25' do
          expect(Worker.new(60, 30, false).can_retire?).to be true
        end
    
        it 'should return true if age is higher than 60 and active years is 25' do
          expect(Worker.new(61, 25, false).can_retire?).to be true
        end
    
        it 'should return true if age is 60 and active years is 25' do
          expect(Worker.new(60, 25, false).can_retire?).to be true
        end
    
        it 'should return true if is veteran and active years is higher than 25' do
          expect(Worker.new(60, 25, false).can_retire?).to be true
        end
      end
    end
    
    

    재구성 방법


    만약 당신이 이미 이렇게 많이 읽었다면, 몇몇 코드가 좀 이상할 수도 있습니다.테스트와 노동자 클래스에서 우리는 많은'신기한 숫자'를 상수로 추출해야 한다.
    우리는 또한 메인 디렉터리에서 모든 상황을 위해 개인 방법을 만들 수 있습니까?공공 방법.
    나는 이 두 가지 잠재적인 재구성을 연습으로 너에게 남겨 줄 것이다.그러나 우리는 지금 테스트를 하고 있기 때문에 만약 우리가 어떤 단계에서 실수를 한다면 그들은 우리에게 알려줄 것이다.

    결론


    나는 네가 프로젝트에서 TCR을 시험해 보라고 격려한다.외부 서버에서 기이한 연속 통합을 할 필요도, 새 라이브러리와의 의존 관계도 필요 없기 때문에 이것은 매우 저렴한 실험이다.일부 파일을 컴퓨터에 저장할 때마다 명령을 실행하는 방법만 필요합니다.
    테스트를 추가할 때, 그것은 당신에게 일종의 게임 체험을 줄 것이다. 이것은 항상 매우 재미있다.또한 편집기에서 실패한 테스트를 삭제하는 규칙은 저장소로 전송된 테스트가 통과되고 있는지 확인하는 추가 안전망을 제공합니다.
    나는 당신이 이 신기술이 유류 코드를 처리할 때 매우 유용하다는 것을 발견하기를 바랍니다.지난 몇 달 동안 나는 이미 여러 번 사용했는데, 이것은 줄곧 일종의 즐거움이었다.

    추가 자원


  • .

  • .

  • VS Code's plugin to run a script on save .
  • Honeybadger 정보


    오소리는 너의 배후에서 계산한다.우리는 유일하게 이상 모니터링, 정상적인 운행 시간 모니터링과cron 모니터링을 간단하고 사용하기 쉬운 플랫폼에 결합시킨 오류 추적기이다.
 우리의 사명: 생산을 길들이고 당신을 더욱 좋고 효율적인 개발자로 만드는 것입니다.  Learn more

    좋은 웹페이지 즐겨찾기