使用Spock测试如何验证json属性键值对是动态输入

时间:2018-05-28 16:46:33

标签: unit-testing groovy spock

如何编写正确的测试,以便测试下面存储在数据库表中的csv数据。在项目以外的输入中,任何内容都可以是可选的。 在这里,item是关键,rest全部作为json格式的一部分,通常它在数据库{"brand": "Brand6", "category": "Category6", "subcategory": "Sub-Category6"}

中看起来像这样

输入:

item,category,subcategory,brand,type,feature
TEST-ITEM6,Category6,Sub-Category6,Brand6
TEST-ITEM7,Category7,Sub-Category7,Brand7,TYPE7,FEATURE7
TEST-ITEM8,Category8,Sub-Category8,Brand8,TYPE8,FEATURE8

尝试过测试案例:

def "Case 3a. Verify New 2 records with two more additional fields along with earlier fields to the same tenant"() {
        expect:
            sql().eachRow("SELECT * FROM item WHERE item IN ('"+item+"')") { row ->

            def dbItem = row[0]
            def dbAttributes = getJsonToObject(row[1])

            def dbCategory = dbAttributes.getAt("category").toString()
            def dbSubCategory = dbAttributes.getAt("subcategory").toString()
            def dbBrand = dbAttributes.getAt("brand").toString()
            def dbType = dbAttributes.getAt("type").toString()
            def dbFeature = dbAttributes.getAt("feature").toString()

            assert dbItem == item
            assert category == dbCategory
            assert subcategory == dbSubCategory
            assert brand == dbBrand
            assert type == dbType
            assert feature == dbFeature
        }

        where:
        item << ['TEST-ITEM6', 'TEST-ITEM7', 'TEST-ITEM8']
        category << ['Category6','Category7', 'Category8']
        subcategory << ['Sub-Category6','Sub-Category7', 'Sub-Category8']
        brand << ['Brand6','Brand7', 'Brand8']
        type <<  ['TYPE7', 'TYPE8']
        feature << ['FEATURE7', 'FEATURE8']
    }

错误:

Condition not satisfied:

type == dbType
|    |  |
TYPE8|  TYPE7
     false
     1 difference (80% similarity)
     TYPE(8)
     TYPE(7)

Expected :TYPE7

Actual   :TYPE8

2 个答案:

答案 0 :(得分:2)

在这种情况下,我建议使用Data Tables,因为它变得更具可读性,更接近您的输入。

虽然类型和功能是可选的,但您需要为它提供一些值。它可以是null,也可以是空ListMap(如果某个商品可以有多种类型/功能)

所以你where阻止可能是这样的:

item | category | subcategory | brand | typeFeatureMap
'TEST-ITEM6' | 'Category6' | 'Sub-Category6' | 'Brand6' | [:] // empty
'TEST-ITEM7' | 'Category7' | 'Sub-Category7' | 'Brand7' | ['TYPE7':'FEATURE7']
'TEST-ITEM8' | 'Category8' | 'Sub-Category8' | 'Brand8' | ['TYPE8':'FEATURE8']

我还建议收集数据然后进行比较,以便解决订购问题。

所以bofore你的eachRow做了类似

的事情
def itemFeatures = [:]

eachRow中执行类似

的操作
itemFeatures.put(dbAttributes.getAt("type").toString(), dbAttributes.getAt("feature").toString())

然后

itemFeatures == typeFeatureMap

虽然没有回答你的问题,但我建议考虑在可能的情况下将测试与数据库分开。 如果为数据库抽象层和业务逻辑创建单独的测试,从长远来看,你会更开心;)

答案 1 :(得分:1)

对于可选字段,您可以像这样使用Elvis运算符?:(对不起,长代码,我建模了数据库和两个新的测试用例,一个有很多可选字段和一个失败测试):

package de.scrum_master.stackoverflow

import spock.lang.Specification
import spock.lang.Unroll

class DataTableWithOptionalItemsTest extends Specification {
  @Unroll
  def "Case 3a. Verify record '#item' with possibly optional fields"() {
    expect:
    testData[item].each { row ->
      def dbItem = row["item"]
      def dbCategory = row["category"]
      def dbSubCategory = row["subcategory"]
      def dbBrand = row["brand"]
      def dbType = row["type"]
      def dbFeature = row["feature"]

      assert dbItem == item
      assert (category ?: dbCategory) == dbCategory
      assert (subcategory ?: dbSubCategory) == dbSubCategory
      assert (brand ?: dbBrand) == dbBrand
      assert (type ?: dbType) == dbType
      assert (feature ?: dbFeature) == dbFeature
    }

    where:
    item         | category    | subcategory     | brand    | type    | feature
    'TEST-ITEM6' | 'Category6' | 'Sub-Category6' | 'Brand6' | null    | null
    'TEST-ITEM7' | 'Category7' | 'Sub-Category7' | 'Brand7' | 'TYPE7' | 'FEATURE7'
    'TEST-ITEM8' | 'Category8' | 'Sub-Category8' | 'Brand8' | 'TYPE8' | 'FEATURE8'
    'TEST-ITEM9' | null        | null            | null     | null    | null
    'TEST-FAIL'  | 'CategoryX' | 'Sub-CategoryX' | 'BrandX' | 'TYPEX' | 'FEATUREX'
  }

  static final testData = [
    'TEST-ITEM6': [
      [
        item       : 'TEST-ITEM6',
        category   : 'Category6',
        subcategory: 'Sub-Category6',
        brand      : 'Brand6',
        type       : 'dummy',
        feature    : null
      ],
      [
        item       : 'TEST-ITEM6',
        category   : 'Category6',
        subcategory: 'Sub-Category6',
        brand      : 'Brand6',
        type       : null,
        feature    : "foo"
      ]
    ],
    'TEST-ITEM7': [
      [
        item       : 'TEST-ITEM7',
        category   : 'Category7',
        subcategory: 'Sub-Category7',
        brand      : 'Brand7',
        type       : 'TYPE7',
        feature    : 'FEATURE7'
      ],
      [
        item       : 'TEST-ITEM7',
        category   : 'Category7',
        subcategory: 'Sub-Category7',
        brand      : 'Brand7',
        type       : 'TYPE7',
        feature    : 'FEATURE7'
      ]
    ],
    'TEST-ITEM8': [
      [
        item       : 'TEST-ITEM8',
        category   : 'Category8',
        subcategory: 'Sub-Category8',
        brand      : 'Brand8',
        type       : 'TYPE8',
        feature    : 'FEATURE8'
      ],
      [
        item       : 'TEST-ITEM8',
        category   : 'Category8',
        subcategory: 'Sub-Category8',
        brand      : 'Brand8',
        type       : 'TYPE8',
        feature    : 'FEATURE8'
      ]
    ],
    'TEST-ITEM9': [
      [
        item       : 'TEST-ITEM9',
        category   : 'Category1',
        subcategory: 'Sub-Category1',
        brand      : 'Brand1',
        type       : 'TYPE1',
        feature    : 'FEATURE1'
      ],
      [
        item       : 'TEST-ITEM9',
        category   : null,
        subcategory: null,
        brand      : null,
        type       : null,
        feature    : null
      ]
    ],
    'TEST-FAIL' : [
      [
        item       : 'TEST-FAIL',
        category   : 'CategoryX',
        subcategory: 'Sub-CategoryX',
        brand      : 'BrandY',
        type       : 'TYPEX',
        feature    : 'FEATUREX'
      ]
    ]
  ]
}