I am a java fresher and I went to an interview recently. They asked a question which was something like: Set up Groovy, test whether a sample json file is valid or not. If it is valid, run the json file. If it is not, print "File is not valid". If file is not found, print "file not found". I was given 2 hours time to do it and I could use the internet.
As I had no idea what groovy was or json was, I searched it and set up groovy but could not obtain the output in two hours. What should I have written? I tried some code but I am sure that it was wrong.
You can use file.exists() to check if the file exists on the filesystem and file.canRead() to check if it can be read by the application. Then use JSONSlurper to parse the file and catch JSONException if the json is invalid:
import groovy.json.*
def filePath = "/tmp/file.json"
def file = new File(filePath)
assert file.exists() : "file not found"
assert file.canRead() : "file cannot be read"
def jsonSlurper = new JsonSlurper()
def object
try {
object = jsonSlurper.parse(file)
} catch (JsonException e) {
println "File is not valid"
throw e
}
println object
To pass the file path argument from the command line, replace def filePath = "/tmp/file.json" with
assert args.size == 1 : "missing file to parse"
def filePath = args[0]
and execute on the command line groovy parse.groovy /tmp/file.json
Related
In my Jenkins Job i checked out a repository. In that repo, there is a file which i want to edit during the job. But it seems that the file is not saved. I have a Method like this:
def updateFile(id, key){
def inputFile = readFile("${workspace}/config/cnf.json")
def inputJSON = new JsonSlurper().parseText(inputFile)
inputJSON."${key}"[0].pref = "${id}"
def result = JsonOutput.toJson(inputJSON)
//here it is changed.
println "result:\n${result}"
inputFile << "${JsonOutput.prettyPrint(result)}"
//and now it is again the old one.
println "Hier: \n ${inputFile}"
}
Problem is, that i can't use "new File" and ".write" or ".append" because Jenkins cant find the File that way.
def inputFile = new File("${workspace}/config/cnf.json") --> no File found
Is there any good way to save the existing File?
if readFile("${workspace}/config/cnf.json") works fine
then to write file use writeFile like this:
writeFile file:"${workspace}/config/cnf.json", text:result
I'm trying to get a unit test working that validates a function that reads credentials from a JSON-encoded file. Since the credentials themselves aren't fixed, the unit test needs to provide some and then test that they are correctly retrieved.
Here is the credentials function:
def read_credentials():
basedir = os.path.dirname(__file__)
with open(os.path.join(basedir, "authentication.json")) as f:
data = json.load(f)
return data["bot_name"], data["bot_password"]
and here is the test:
def test_credentials(self):
with patch("builtins.open", mock_open(
read_data='{"bot_name": "name", "bot_password": "password"}\n'
)):
name, password = shared.read_credentials()
self.assertEqual(name, "name")
self.assertEqual(password, "password")
However, when I run the test, the json code blows up with a decode error. Looking at the json code itself, I'm struggling to see why the mock test is failing because json.load(f) simply calls f.read() then calls json.loads().
Indeed, if I change my authentication function to the following, the unit test works:
def read_credentials():
# Read the authentication file from the current directory and create a
# HTTPBasicAuth object that can then be used for future calls.
basedir = os.path.dirname(__file__)
with open(os.path.join(basedir, "authentication.json")) as f:
content = f.read()
data = json.loads(content)
return data["bot_name"], data["bot_password"]
I don't necessarily mind leaving my code in this form, but I'd like to understand if I've got something wrong in my test that would allow me to keep my function in its original form.
Stack trace:
Traceback (most recent call last):
File "test_shared.py", line 56, in test_credentials
shared.read_credentials()
File "shared.py", line 60, in read_credentials
data = json.loads(content)
File "/home/philip/.local/share/virtualenvs/atlassian-webhook-basic-3gOncDp4/lib/python3.6/site-packages/flask/json/__init__.py", line 205, in loads
return _json.loads(s, **kwargs)
File "/usr/lib/python3.6/json/__init__.py", line 367, in loads
return cls(**kw).decode(s)
File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
I had the same issue and got around it by mocking json.load and builtins.open:
import json
from unittest.mock import patch, MagicMock
# I don't care about the actual open
p1 = patch( "builtins.open", MagicMock() )
m = MagicMock( side_effect = [ { "foo": "bar" } ] )
p2 = patch( "json.load", m )
with p1 as p_open:
with p2 as p_json_load:
f = open( "filename" )
print( json.load( f ) )
Result:
{'foo': 'bar'}
I had the exact same issue and solved it. Full code below, first the function to test, then the test itself.
The original function I want to test loads a json file that is structured like a dictionary, and checks to see if there's a specific key-value pair in it:
def check_if_file_has_real_data(filepath):
with open(filepath, "r") as f:
data = json.load(f)
if "fake" in data["the_data"]:
return False
else:
return True
But I want to test this without loading any actual file, exactly as you describe. Here's how I solved it:
from my_module import check_if_file_has_real_data
import mock
#mock.patch("my_module.json.load")
#mock.patch("my_module.open")
def test_check_if_file_has_real_data(mock_open, mock_json_load):
mock_json_load.return_value = dict({"the_data": "This is fake data"})
assert check_if_file_has_real_data("filepath") == False
mock_json_load.return_value = dict({"the_data": "This is real data"})
assert check_if_file_has_real_data("filepath") == True
The mock_open object isn't called explicitly in the test function, but if you don't include that decorator and argument you get a filepath error when the with open part of the check_if_file_has_real_data function tries to run using the actual open function rather than the MagicMock object that's been passed into it.
Then you overwrite the response provided by the json.load mock with whatever you want to test.
Below is my JSON script.
PRAMS.json
{
"JSON" : {
"test": "iTEST",
"testname": "BOV-VDSL-link-Rateprofile-CLI-Test-1",
"params": [
{
"n2x_variables / config_file": "C:/Program Files (x86)/Agilent/N2X/RouterTester900/UserData/config/7.30 EA SP1 Release/OSP Regression/BOV/Bov-data-1-single-rate-profile.xml"
},
{
"n2x_variables / port_list": "303/4 303/1"
}
]
}
}
Below is my groovy script and I am sending params.json script to the same groovy script.
parseJSON.groovy
import groovy.json.JsonSlurper
def jsonFile = new File("../var/PARAMS.json")
def keys = new JsonSlurper().parse("jsonFile.text")
println keys.keySet()
I am getting below error :
****No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile.text]****
Can any one please help me ?
Thanks for reply, I am new to this json.
I am unable to share screen shot, showing error message when I am trying to upload image but i can give total error message :
developer#cn-vm-yourname:~/Desktop/kramdeni/vars$ groovy parseJSON.groovy
Caught: groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile]
Possible solutions: parse(java.io.Reader), parseText(java.lang.String), use([Ljava.lang.Object;), wait(), grep(), any()
groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.lang.String) values: [jsonFile]
Possible solutions: parse(java.io.Reader), parseText(java.lang.String), use([Ljava.lang.Object;), wait(), grep(), any()
at parseJSON.run(parseJSON.groovy:3)
developer#cn-vm-yourname:~/Desktop/kramdeni/v
and my expected output is to print only all values without keys in required order.
To get above result I wrote groovy script like below :
import groovy.json.JsonSlurper
label = "test testname params"
def jsonFile = new File('PARAMS.json')
def par = new JsonSlurper().parse(jsonFile)
println keys.keySet()
def command = ""
keys = label.split(" ")
println "keys: " + keys
for (key in keys) {
command += par[key] + " "
}
println "command: " + command
import groovy.json.JsonSlurper
def src = new File("MYPATH/MY.json")
//next line downloads json from URL:
//def src = new URL("http://date.jsontest.com")
def json = new JsonSlurper().parse( src.newInputStream() )
json.each{ k,v-> println "$k = $v" }
try it:
https://groovy-playground.appspot.com/#?load=ccceffd570c6ee176bc6f1fcdafdcbe0
if you have exception
groovy.lang.MissingMethodException: No signature of method:
groovy.json.JsonSlurper.parse() is applicable for argument types:
(java.io.BufferedInputStream)
Possible solutions: parse(java.io.Reader) ...
that means you have quite old version of groovy, however it suggests solution - try to get reader from file:
def src = new File("MYPATH/MY.json")
def json = new JsonSlurper().parse( src.newReader("UTF-8") )
json.each{ k,v-> println "$k = $v" }
but to continue you have to find version of your groovy, then find documentation for your version and continue developing referencing it
for example in groovy 1.8.6 there are only two parse methods in JsonSlurper:
http://docs.groovy-lang.org/1.8.6/html/api/groovy/json/JsonSlurper.html
and in the latest groovy much more...
http://docs.groovy-lang.org/latest/html/gapi/groovy/json/JsonSlurper.html
Update:
I want to check a JSON document on his structure. I created a JSR223 Assertion with language groovy. My code to check the JSON structure looks like this:
import groovy.json.*;
import org.apache.jmeter.samplers;
def response = prev.getResponseDataAsString();
log.info("Response" + response);
def json = new JsonSlurper().parseText(response);
//tests
def query = json.query;
assert query instanceof String;
def totalResults = json.totalResults;
assert query instanceof Integer;
def from = json.from;
assert from instanceof Integer;
def to = json.to;
assert to instanceof Integer;
assertionResult = new AssertionResult("Assertion failed! See log file.");
assertionResult.setError(true);
assertionResult.setFailureMessage(e.toString());
The validation in the JMeter logfile works great.
But in my View Result Tree, i got the following error message:
Assertion error: true
Assertion failure: false
Assertion failure message: javax.script.ScriptException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script27.groovy: 2: unable to resolve class org.apache.jmeter.samplers
# line 2, column 1.
import org.apache.jmeter.samplers;
^
Script27.groovy: 21: unable to resolve class AssertionResult
# line 21, column 19.
assertionResult = new AssertionResult("Assertion failed! See log file.");
^
2 errors
I want to see if the test result is successful or not.
How to fix this issue?
Don't instantiate AssertionResult class, it is pre-defined
Don't use Groovy assert keyword, it won't fail the parent sampler as expected, refer below example simple code
if (1 != 2) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage("1 is not equal to 2")
}
once you get it working like below:
you can start modifying your tests as required
See How to Use JMeter Assertions in Three Easy Steps guide to learn more about using assertions in JMeter tests.
while running this script i am getting the following error...
ERROR: getTest failed. No JSON object could be decoded
My code is:
import json
import urllib
class test:
def getTest(self):
try:
url = 'http://www.exapmle.com/id/123456/'
json_ = urllib.urlopen(url).read()
self.id = json.loads(json_)
print self.id
except Exception, e:
print "ERROR: getTest failed. %s" % e
if __name__ == "__main__":
ti = test()
ti.getTest()
while opening this url "http://www.exapmle.com/id/123456/" in browser i am getting json format data, but why it is throwing an error?
Print the json_ before calling json.loads(). If there is in an error in your url, urllib does not necessarily throw an exception, it might just retrieve some error page (like with the provided url), that is not valid json.