본문 바로가기

배움의 즐거움/프로그래밍

(10) Graphql-ruby - 스키마 테스팅

반응형





Schema Testing

GraphQL 스키마를 테스트할 여러가지 방법이 있다.

  • 스키마를 테스트 하지말고 객체를 대신 테스트해라

  • GraphQL 쿼리를 실행하고 결과를 테스트해라


Don’t test the schema

GraphQL 스키마의 behavior을 테스트할 가장 쉬운 방법은 behavior을 따로 객체로 추출하여 해당 객체를 독립적으로 테스트 하는 것이다. 레일에서 컨트롤러 테스트로 모델을 테스트하지 않는다. 비슷하게 시스템의 "low-level" 파트를 자체적으로 테스트 할 수 있다.


예를 들어, 자기 자신의 값을 계산하는 필드를 보자.

class PostType < GraphQL::Schema::Object
  # ...
  field :is_trending, Boolean, null: false

  def is_trending
    recent_comments = object.comments.where("created_at < ?", 1.day.ago)
    recent_comments.count > 100
  end
end


새로운 클래스를 만들어서 GraphQL 스키마에 적용함으로써 이를 개선할 수 있다.

# app/models/post/trending.rb
class Post
  class Trending
    TRENDING_COMMENTS_COUNT = 100
    def initialize(post)
      @post = post
    end

    def value
      recent_comments = @post.comments.where("created_at < ?", 1.day.ago)
      recent_comments.count > TRENDING_COMMENTS_COUNT
    end
  end
end

# ....

class PostType < GraphQL::Schema::Object
  # ...
  field :is_trending, Boolean, null: false

  def is_trending
    Post::Trending.new(object).value
  end
end


이렇게 함으로써 behavior이 GraphQL 스키마와 결합되지 않도록 개선할 수 있다. 또한 테스트하기도 더 편하다. 이제 단순히 calculation 클래스만 유닛테스트 할 수 있다. 

# spec/models/post/trending_spec.rb
RSpec.describe Post::Trending do
  let(:post) { create(:post) }
  let(:trending) { Post::Trending.new(post) }

  describe "#value" do
    context "when there are no recent comments" do
      it "is false" do
        expect(trending.value).to eq(false)
      end
    end

    context "when there are more than 100 recent comments" do
      before do
        101.times { create(:comment, post: post) }
      end

      it "is true" do
        expect(trending.value).to eq(true)
      end
    end
  end
end


Executing GraphQL queries


때때로는 처음부터 끝까지 테스트를 해야할 때가 있다. 이러한 방식은 많은 메모리를 요구로 하지만 전체로 봤을 때는 "sanity check" 를 하는 것은 좋다.


테스트의 스키마에서 쿼리를 실행할 수 있다. 예를 들면 이런식으로 가능하다.

RSpec.describe MySchema do
  # `context`와 `variables`을 더 다양한 scopes 에서
  # 오버라이드 할 수 있다.
  let(:context) { {} }
  let(:variables) { {} }
  # 쿼리를 실행하기 위해 `result`를 호출
  let(:result) {
    res = MySchema.execute(
      query_string,
      context: context,
      variables: variables
    )
    # 에러가 있다면 출력
    if res["errors"]
      pp res
    end
    res
  }

  describe "a specific query" do
    # `result` 를 위한 쿼리 제공
    let(:query_string) { %|{ viewer { name } }| }

    context "when there's no current user" do
      it "is nil" do
        # 호출 `result`
        expect(result["data"]["viewer"]).to eq(nil)
      end
    end

    context "when there's a current user" do
      # 오버라이드 `context`
      let(:context) {
        { current_user: User.new(name: "ABC") }
      }
      it "shows the user's name" do
        user_name = result["data"]["viewer"]["name"]
        expect(user_name).to eq("ABC")
      end
    end
  end
end

* 해당 글은 번역기 돌리다가 크롬 번역기 말도 안되는 해석에 지친 본인이 나중에 참고할 의도로 대충대충 발로 해석한 것이니 참고용으로만 사용하시길 바랍니다.

* 출처: http://graphql-ruby.org/schema/testing.html


반응형