GraphQL测试实践

Posted ThoughtWorks洞见

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GraphQL测试实践相关的知识,希望对你有一定的参考价值。

我们很熟悉以REST实现的API,可以用任何能够发出http 请求的库或者工具来测试REST API。 去年随着GraphQL在全球风靡,它也出现在了最近两期的 中,当我们面对新的GraphQL APi时,QA应如何应对? 知彼知己,方能百战百胜,下面让我们首先来看看什么是GraphQL,它和传统的REST API又有什么不同?

什么是GraphQL ?

Graph +  Query L anguage =图表化(可视化)查询语言
是一种描述客户端如何向服务端请求数据的API语法,类似于 RESTful API 规范。由Facebook开发,用于替换RESTful API。服务端可以用任何的语言实现。
由于这篇不是GraphQL科普文,我们大概介绍下几个重要概念,给后面测试做铺垫。

Schema:Schema由服务端来定义,用于定义API接口,并依靠Schema来生成文档以及对客户端请求进行校验。Schema只是一个概念,它是由各种数据类型及其字段组成,而每个类型的每个字段都有相应的函数来返回数据,且Schema里的字段可以聚合其他Schema,我们可以将Schema理解为多个Query组成的一张表。

Type: 类型是用来描述 API 外观的自定义对象。 对于数据模型的抽象是通过Type来描述的,每一个Type有若干Field组成,每个Field又分别指向某个Type。
Query: 有了Schema 有了Type,相对于传统的API的CRUD,我们接下来需要怎么做,Query就出现。 Query 的查询语法和格式受 Schema 约束,而 Query,Mutation,Subscription 是 Query 的三种类型,分别对应不同的业务场景。
总结下:
  1. 前端自己定义返回的数据及结构,降低前后端沟通成本

  2. 无需编写接口文档(GraphQL会根据schema自动生成API文档)

  3. Schema拼接,可以组合和连接多个GraphQL API,合并为一个,减少请求次数

  4. GraphQL是强类型的,通过它,可以在执行之前验证 GraphQL 类型系统中的查询, 它帮助我们构建更强大的 API。

如何简单快速的手动测试GraphQL?

我们先来看看 GraphQL与RESTful的区别:
GraphQL测试实践
上图我们其实可以发现一些蛛丝马迹,再来个更直观的以

https://www.squarefoot.com.hk/en/ 

GraphQL测试实践

传统的REST请求
无论GET还是POST 都是以REST Server Host URL 加请求的Path 再加Query 或者Body 来发送请求。
而对于GraphQL
GraphQL测试实践
则是GraphQL Server Host Url 加Query 或者Body 来发送请求。
所以第一个不同就是GraphQL 缺失了path。 但从请求URL上我们无法辨别GraphQL到底干了什么,我需要进一步的观察请求的body REST api 请求POST带的请求的数据。 同样GraphQL它也是发送的POST请求,也是带的数据。
但是不同点就在于内容。 我们来看看GraphQL Body
GraphQL测试实践
{ 

"operationName":"FeaturedProperty",

 "variables":{ 


 },

 "query":"query FeaturedProperty {  featuredListing(channel: \"sale\", pageSize: 4) {    items {      id      title      subtitle      description      propertyType      prices {        min        max        monthlyPayment        currency        symbol        label        type        __typename      }      address {        lat        lng        formattedAddress        __typename      }      propertyType      cover {        url        urlTemplate        __typename      }      organisations {        id        name        color        logo {          url          urlTemplate          __typename        }        type        __typename      }      listers {        id        type        name        __typename      }      tier      channels      attributes {        sizeUnit        pricePSF        minimumPricePerSizeUnit        maximumPricePerSizeUnit        builtUp        landArea        bedroom        bathroom        __typename      }      multilanguagePlace {        enGB {          level1          level2          level3          __typename        }        idID {          level1          level2          level3          __typename        }        zhHK {          level1          level2          level3          __typename        }        zhCN {          level1          level2          level3          __typename        }        __typename      }      __typename    }    __typename  }}"

}

GraphQL 请求的Body里面包含的是我们在GraphQL server中 定义的Query 和Schema中的字段。 而REST POST请求则直接包含的是我们要发送的数据。 所以GraphQL 那里客户端 可以拿自己想拿的数据,但REST api 只能请求 server 定义的api。
回到正题,刚才主要还是停留在REST api与GraphQL一些基本的区别,那么怎么手动测试。
对于GraphQL 我们需要借助一些第三方库来测试,例如: graphiql graphql-playground  都能帮我们很好进行基本的验证。
GraphQL测试实践
上面无论是graphiql还是graphql-playground 我们都能够利用它发送具体请求,来查看结果是否正确。 但是当查询的api 返回几万条,我们需要验证某一些数据与逻辑的正确性时,graphiql与graphql-playground 就显得力不从心。
怎么办? 我们需要一种能发出GraphQL 请求并且有相应断言框架的工具。
我们可以利用代码来实现,但对于项目中所有角色,尤其是一些没有代码经验的人,让他们去看代码实现是非常痛苦的,自动化测试本质是能够帮我们快速回归,验证完成功能是否受到影响,并且你的测试代码或工具能够让每个角色轻松理解并能够快速简单使用,而不是秀你的代码多么炫酷用了多么复杂的算法,一切以实用为本。
基于以上事实,我选择所有角色都用过Postman工具来实现GraphQL 手动测试。
首先怎么将GraphQL于Postman结合?
如果你的前端不是服务器渲染的话,我们可以从chrom dev tools 查看到客户端发生的请求。
如果是服务器渲染的话,我们可以利用上面说过的graphiql与graphql-playground去手动执行需要测试的请求,然后同样在chrome dev tools 查看具体的请求。
我们知道具体请求的Query内容,有的内容很长,难道让我们一个一个字全打到Postman上?
GraphQL测试实践
这里有一个小技巧,鼠标右键在chrome dev tools 具体请求上点击,然后选择copy 选择copy as curl 这样就能简单复杂这条请求。
步骤二,打开Postman 创建完我们的work space后,选择import 在将复制的请求 Paste Raw Text
GraphQL测试实践
导入后 就会在我们创建的work space里面创建这条测试
GraphQL测试实践
步骤三 利用Postman test script 来编写对应检查点
GraphQL测试实践
光有了这种可视化的脚本运行是远远不够的,我们需要将我们编写的测试脚本与CI集成,并入我们整个开发流程中才能算完美,Postman提供了newman 这个第三库方便我们能够将Postman中export出的脚本,在命令行中快速执行,并结合Docker与Linux Shell使我们能够更方便的与任何CI集成。

#!/usr/bin/env bash

set -ex

docker run --rm -v $(pwd):/etc/postman  \

  -w /etc/postman  \

  -t postman/newman_ubuntu1404 \

  run  "./postman/test.postman_collection.json"  \

  --environment="./postman/test.postman_environment.json" \

  --timeout-request  20000

最新的版本的Postman 已经支持了对于GraphQL 测试,如果你还用的旧版本的Postman,请参考以上步骤,如果你已经下载了最新版本的Postman, potman官网已经给了说明文档, https://learning.getpostman.com/docs/postman/sendingapirequests/GraphQL/ 请参考链接。

利用测试脚本实现GraphQL自动化api测试

上面主要介绍如何手动测试GraphQL,当然我们也可以利用代码来实现GraphQL 测试。
传统上我们测试RESTful时,大部分人可能选择的mocha chai supertest 这个库作为测试框架 来编写API测试,通过上面的文章,我们了解到GraphQL 请求的底层依然还是http request,所以我们依然能够采用这套非常成熟的架构,但是我们今天要将mocha 替换成AVA,因为它支持并发,能够帮我们进一步的提升测试效率。
安装依赖库

npm init -y

npm i --save-dev mocha chai ava

测试代码如下

import test from 'ava';

import { expect,should } from "chai"

import supertest from 'supertest';

const server = supertest.agent("http://localhost:3000/GraphQL");

test('test grahphql api',async (t)=>{

  const res = await server

  .post("/")

    .send(

  {"operationName":null,"variables":{},"query":"{\n  student(id: \"1\") {\n    id\n    name\n    age\n    sex\n  }\n}\n"}

  )

    .set('Content-Type', "application/json")

  .expect(200) 

  .end();

  res.body.user.should.have.property('name')

    

  });

上面的代码看起来也挺简单,但是这不是我们最优方案,我们可以看到 request 的query 由于要遵循GraphQL 规范,并不是我们常见的json对象,我们需要寻找一种能够代替supertest 发送规范化GraphQL Query 和 Mutation 请求的工具,ApolloClient就是一个不错的选择。
安装对应依赖库

npm --save-dev install apollo-boost  GraphQL

测试代码如下

import test from 'ava';

import { gql } from "apollo-boost";

import ApolloClient from "apollo-boost/lib/index";

import fetch from 'node-fetch';

const client = new ApolloClient({

    uri: "http://localhost:8080/GraphQL",

    fetch: fetch

  });

  const GET_STUDENT = gql`

  query($id: String!) {

    student(id:$id){

        id

        name

        age

        sex

      }

  }

`;


test('first scenario',async (t) => {

    const res =await client

    .query({

      query: GET_STUDENT,

      variables: {

        id: '1',

      },

    });

    console.log("+++++++",res.data);

    t.is(res.data.student.id, '1')

});


运行通过

qilei/study/ava-api-testing

▶ npx ava   -v

+++++++ { student:

   { id: '1', name: 'Tom', age: 25, sex: true, __typename: 'Student' } }

  ✔ grahpql api testing (115ms)

  1 test passed

上面的ApolloClient 与ava.js 测试架构,可以复用之前开发代码编写过query或mutation,更适合dev快速编写api集成测试。
综上,对于这些新的事物,我们要看清它的本质,才能快速理解它的架构及原理,从而进一步找到适配的测试框架或工具,来帮助我们更好的提升项目质量。 最后还要再次强调,自动化测试框架的设计与选型,应该以人为本,适合项目所有成员的工具,才能够提升整体团队的协作效率。

- 相关阅读 -

点击【阅读原文】可至洞见网站查看原文&绿色字体部分的相关链接。

本文版权属ThoughtWorks公司所有,如需转载请在后台留言联系。

以上是关于GraphQL测试实践的主要内容,如果未能解决你的问题,请参考以下文章

将 GraphQL 片段与 Apollo Hooks 一起使用时出错

你如何在 python 中处理 graphql 查询和片段?

在 Java 的 GraphQL 查询中添加片段

GraphQL 片段的片段

盖茨比没有找到graphql片段

在graphql中嵌套片段