如何使用 graphql-ruby 测试 GraphQL 模式?
How to test a GraphQL schema with graphql-ruby?
我的目标是在 ruby 中测试我的 GraphQL 模式的类型,我正在使用 graphql-ruby gem.
我找不到这方面的任何最佳实践,所以我想知道测试架构的字段和类型的最佳方法是什么。
gem 建议不要直接测试架构 http://graphql-ruby.org/schema/testing.html,但我仍然发现了解架构何时意外更改很有价值。
有这样的类型:
module Types
class DeskType < GraphQL::Schema::Object
field :id, ID, 'Id of this Desk', null: false
field :location, String, 'Location of the Desk', null: false
field :custom_id, String, 'Human-readable unique identifier for this desk', null: false
end
end
我的第一个方法是在 GraphQL::Schema::Object 类型中使用 fields
散列,例如:
Types::DeskType.fields['location'].type.to_s => 'String!'
创建一个 RSpec 匹配器,我可以想出如下所示的测试:
RSpec.describe Types::DeskType do
it 'has the expected schema fields' do
fields = {
'id': 'ID!',
'location': 'String!',
'customId': 'String!'
}
expect(described_class).to match_schema_fields(fields)
end
end
虽然这种方法有一些缺点:
- 匹配器中的代码取决于 class GraphQL::Schema::Object 的实现,任何重大更改都会在更新后破坏测试套件。
- 我们正在重复代码,测试断言类型中的相同字段。
- 编写这些测试变得乏味,这使得开发人员不太可能编写它们。
我觉得对我采用的第一种方法的改进是对 GraphQL 架构使用快照测试,而不是一个一个地测试每个 types/mutation 架构,我创建了一个测试:
RSpec.describe MySchema do
it 'renders the full schema' do
schema = GraphQL::Schema::Printer.print_schema(MySchema)
expect(schema).to match_snapshot('schema')
end
end
此方法使用 rspec-snapshot gem, see my PR here 的略微修改版本。
gem 不允许你像在 Jest 中那样使用单个命令更新快照,所以我还创建了一个 rake 任务来删除当前快照:
namespace :tests do
desc 'Deletes the schema snapshot'
task delete_schema_snapshot: :environment do
snapshot_path = Rails.root.join('spec', 'fixtures', 'snapshots', 'schema.snap')
File.delete(snapshot_path) if File.exist?(snapshot_path)
end
end
有了这个,当模式被修改时,你会得到一个漂亮的 RSpec 差异。
顶级架构对象有一个 #execute method。你可以用它来编写像
这样的测试
RSpec.describe MySchema do
it 'fetches an object' do
id = 'Zm9vOjE'
query = <<~GRAPHQL
query GetObject($id: ID!) {
node(id: $id) { __typename id }
}
GRAPHQL
res = described_class.execute(
query,
variables: { id: id }
)
expect(res['errors']).to be_nil
expect(res['data']['node']['__typename']).to eq('Foo')
expect(res['data']['node']['id']).to eq(id)
end
end
#execute 方法的 return 值将是传统的 HTTP 样式响应,作为字符串键控哈希。 (实际上它是一个 GraphQL::Query::Result,但它将大部分内容委托给了一个嵌入式哈希。)
您似乎想测试您的模式,因为您想知道它是否会破坏客户端。基本上你应该避免这种情况。
相反,您可以使用像这样的宝石:graphql-schema_comparator
来打印重大更改。
- 我建议有一个 rake 任务来转储你的模式(并在你的 repo 中提交它)。
- 您可以编写一些规范来检查模式是否已转储 - 然后您将确保,您始终拥有最新的模式转储。
- 设置您的 CI 以将当前分支的模式与 master 分支上的模式进行比较。
- 如果架构有危险或重大更改,则构建失败。
- 您甚至可以使用 schema-comparator 生成架构变更日志 ;) 或者您甚至可以使用松弛通知将任何架构更改发送到那里,以便您的团队可以轻松跟踪任何更改。
我的目标是在 ruby 中测试我的 GraphQL 模式的类型,我正在使用 graphql-ruby gem.
我找不到这方面的任何最佳实践,所以我想知道测试架构的字段和类型的最佳方法是什么。
gem 建议不要直接测试架构 http://graphql-ruby.org/schema/testing.html,但我仍然发现了解架构何时意外更改很有价值。
有这样的类型:
module Types
class DeskType < GraphQL::Schema::Object
field :id, ID, 'Id of this Desk', null: false
field :location, String, 'Location of the Desk', null: false
field :custom_id, String, 'Human-readable unique identifier for this desk', null: false
end
end
我的第一个方法是在 GraphQL::Schema::Object 类型中使用 fields
散列,例如:
Types::DeskType.fields['location'].type.to_s => 'String!'
创建一个 RSpec 匹配器,我可以想出如下所示的测试:
RSpec.describe Types::DeskType do
it 'has the expected schema fields' do
fields = {
'id': 'ID!',
'location': 'String!',
'customId': 'String!'
}
expect(described_class).to match_schema_fields(fields)
end
end
虽然这种方法有一些缺点:
- 匹配器中的代码取决于 class GraphQL::Schema::Object 的实现,任何重大更改都会在更新后破坏测试套件。
- 我们正在重复代码,测试断言类型中的相同字段。
- 编写这些测试变得乏味,这使得开发人员不太可能编写它们。
我觉得对我采用的第一种方法的改进是对 GraphQL 架构使用快照测试,而不是一个一个地测试每个 types/mutation 架构,我创建了一个测试:
RSpec.describe MySchema do
it 'renders the full schema' do
schema = GraphQL::Schema::Printer.print_schema(MySchema)
expect(schema).to match_snapshot('schema')
end
end
此方法使用 rspec-snapshot gem, see my PR here 的略微修改版本。
gem 不允许你像在 Jest 中那样使用单个命令更新快照,所以我还创建了一个 rake 任务来删除当前快照:
namespace :tests do
desc 'Deletes the schema snapshot'
task delete_schema_snapshot: :environment do
snapshot_path = Rails.root.join('spec', 'fixtures', 'snapshots', 'schema.snap')
File.delete(snapshot_path) if File.exist?(snapshot_path)
end
end
有了这个,当模式被修改时,你会得到一个漂亮的 RSpec 差异。
顶级架构对象有一个 #execute method。你可以用它来编写像
这样的测试RSpec.describe MySchema do
it 'fetches an object' do
id = 'Zm9vOjE'
query = <<~GRAPHQL
query GetObject($id: ID!) {
node(id: $id) { __typename id }
}
GRAPHQL
res = described_class.execute(
query,
variables: { id: id }
)
expect(res['errors']).to be_nil
expect(res['data']['node']['__typename']).to eq('Foo')
expect(res['data']['node']['id']).to eq(id)
end
end
#execute 方法的 return 值将是传统的 HTTP 样式响应,作为字符串键控哈希。 (实际上它是一个 GraphQL::Query::Result,但它将大部分内容委托给了一个嵌入式哈希。)
您似乎想测试您的模式,因为您想知道它是否会破坏客户端。基本上你应该避免这种情况。
相反,您可以使用像这样的宝石:graphql-schema_comparator
来打印重大更改。
- 我建议有一个 rake 任务来转储你的模式(并在你的 repo 中提交它)。
- 您可以编写一些规范来检查模式是否已转储 - 然后您将确保,您始终拥有最新的模式转储。
- 设置您的 CI 以将当前分支的模式与 master 分支上的模式进行比较。
- 如果架构有危险或重大更改,则构建失败。
- 您甚至可以使用 schema-comparator 生成架构变更日志 ;) 或者您甚至可以使用松弛通知将任何架构更改发送到那里,以便您的团队可以轻松跟踪任何更改。