javajsongroovyspockgeb

How to generate data table dynamically using json file?


I am new to geb, spock and groovy. The script I am working on is I have a groovy class containing my json. In my groovy class I count how many objects are there in the json and for each object I read key values and then I have another unit testSpec in spock and Geb where I have create my login test script to login to the application which is very simple. The scenario I am trying to achieve is I want to generate data table in spock test based on data present in json file. Here what I have achieved till now My InputDataJson.groovy file

package resources

import geb.spock.GebSpec
import groovy.json.JsonSlurper
import spock.lang.Shared

class InputDataJson extends GebSpec{
@Shared
  def  inputJSON,
idValue, passwordValue, jsonSize

@Shared
def credsList = []


def setup() {

  inputJSON = '''{
          "validLogin":{
          "username" : "abc",
          "password" : "correcttest"
          },
          "invalidLogin":{
          "username" : "xyz",
          "password" : "badtest"
          }
      }'''

  def JsonSlurper slurper = new JsonSlurper()
  def TreeMap parsedJson = slurper.parseText(inputJSON)
  jsonSize = parsedJson.size()

  Set keySet = parsedJson.keySet()
  int keySetCount = keySet.size()
  for(String key : keySet){
    credsList.add(new Creds(username: parsedJson[key].username,password: 
parsedJson[key].password))
  } 
}
}

and here is my sample spock geb test

package com.test.demo


import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
import pages.LoginPage
import resources.InputDataJson

/**
* See the API for {@link grails.test.mixin.support.GrailsUnitTestMixin} for usage instructions
*/
@TestMixin(GrailsUnitTestMixin)
class SampleTest1Spec extends InputDataJson {

  def credentialsList = []
      def setup() {
        credentialsList = credsList
          }

       def cleanup() {
       }

       void "test something"() {
          }
  def "This LoginSpec test"() {
      given:
      to LoginPage

  when:'I am entering username and password'
      setUsername(username)
      setPassword(password)
      login()

      then: "I am being redirected to the homepage"
      println("Hello")


    where:
      [username,password]<< getCreds()
      //credsList[0]['username'] | credsList[0]['password']



  }

  def getCreds(){
  println(" CREDS inside " + credsList)
   println(" credentialsList : " + credentialsList)
  }

}

The problem is when I run this test in debug mode (I understand in spock test first where clause is executed first) my credsList and credentialsList both are coming null and when execution mode reaches to "when" section it fetches the correct user name and password. I am not sure where I am making mistake. Any help is well appreciated.


Solution

  • Leonard Brünings said:

    try replacing setup with setupSpec

    Exactly, this is the most important thing. You want something that is initialised before any feature method or iteration thereof starts. So if you want to initialise static or shared fields, this is the way to go.

    Additionally, credsList contains Creds objects, not just pairs of user names and passwords. Therefore, if you want those in separate data variables, you need to dereference them in the Creds objects. Here is a simplified version of your Spock tests without any Grails or Geb, because your question is really just a plain Spock question:

    package de.scrum_master.stackoverflow.q71122575
    
    class Creds {
      String username
      String password
    
      @Override
      String toString() {
        "Creds{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'
      }
    }
    
    package de.scrum_master.stackoverflow.q71122575
    
    import groovy.json.JsonSlurper
    import spock.lang.Shared
    import spock.lang.Specification
    
    class InputDataJson extends Specification {
      @Shared
      List<Creds> credsList = []
    
      def setupSpec() {
        def inputJSON = '''{
          "validLogin" : {
            "username" : "abc",
            "password" : "correcttest"
          },
          "invalidLogin" : {
            "username" : "xyz",
            "password" : "badtest"
          }
        }'''
    
        credsList = new JsonSlurper().parseText(inputJSON)
          .values()
          .collect { login -> new Creds(username: login.username, password: login.password) }
      }
    }
    
    package de.scrum_master.stackoverflow.q71122575
    
    import spock.lang.Unroll
    
    class CredsTest extends InputDataJson {
      @Unroll("verify credentials for user #username")
      def "verify parsed credentials"() {
        given:
        println "$username, $password"
    
        expect:
        username.length() >= 3
        password.length() >= 6
    
        where:
        cred << credsList
        username = cred.username
        password = cred.password
      }
    }
    

    The result in IntelliJ IDEA looks like this:

    IDEA Spock test result

    Try it in the Groovy web console