# imports
%matplotlib inline
from itertools import product
import json, matplotlib, pyodbc, pandas, uuid, copy
import matplotlib.pyplot as plt
import numpy as np

# some basic data
a = [[True,False],['Purchase','Refinance','LoanModification'],['AZ'],[1,2,3,4]]
pandas.DataFrame(a)

"""
Explanation: Testing your APIs using Generated Postman Tests

Author Matthew Oliver
Email matthewaustinoliver@gmail.com

Theory

full combinatoric coverage is not usually feasible in real-world systems
pairwise, base choice, each choice, or any number of other testing techniques may be required
pairwise testing catches ~50-90% of defects - [kuhn]

Tools
We'll be leveraging the following third-party tools for our test example:

Postman - Chrome Extension / Packaged App
Newman - a NodeJS based Postman CLI

Technique
To illustrate the technique we will leverage

A sample REST WebAPI project
Python Scripts - to generate all input combinations and create our postman collections
Newman - to run our collections and report the output

We will be naively performing an exhaustive combinatorial 
test due to the small app domain.
Technique - Example API
We'll create a simple .net webapi project consisting of two routes:

GET /api/Examples
POST /api/Examples

The API will produce errors for some value combinations.
Technique - The Dataset
End of explanation
"""


len(a[0])*len(a[1])*len(a[2])*len(a[3])

"""
Explanation: Technique - Combinations
To cover all combinations of will require n0 * n1 * ... nn combinations
End of explanation
"""


combinations = list(product(*a))
pandas.DataFrame(combinations)

"""
Explanation: Lets see what that looks like by generating all unique combinations.
End of explanation
"""


for combination in combinations:
    valMap = {'isVal':combination[0],'loanType':combination[1],
              'state':combination[2],'policyCount':combination[3]}
    print(json.dumps(valMap, ensure_ascii=False))

"""
Explanation: We can then convert the combinations to a JSON object which will
be our data contract in this example.
End of explanation
"""


with open('CombinatorialTesting.json.postman_collection') as data_file:    
    postman_coll = json.load(data_file)
postman_coll

"""
Explanation: Next, to be able to use our tests in postman we need to create a postman collection.
First, we'll import an existing postman collection to a json object.
End of explanation
"""


with open('CombinatorialTesting.json.postman_collection') as data_file:    
    postman_coll = json.load(data_file)
requestTemplate = copy.deepcopy(postman_coll['requests'][0])
idx = 0;
del(postman_coll['requests'][0])
for combination in combinations:
    valMap = {'isVal':combination[0],'loanType':combination[1],
              'state':combination[2],'policyCount':combination[3]}
    someobj = copy.deepcopy(requestTemplate)
    idx+=1
    someobj['name'] = str('Example ')+str(idx)
    valJson = json.dumps(valMap, ensure_ascii=False)
    someobj['rawModeData'] = str(valJson)
    someid = str(uuid.uuid4())
    someobj['id'] = someid
    someobj['url'] = "{{Url}}/Examples"
    someobj['method'] = "POST"
    someobj['tests'] = str('tests["Status code is 201"] = responseCode.code === 201;')
    postman_coll['order'].append(someid)
    postman_coll['requests'].append(someobj)

with open('CombinatorialTesting2.json.postman_collection', 'w') as outfile:
    json.dump(postman_coll, outfile)

"""
Explanation: Next we manipulate the template using our unique request combinations and
dump it back out to the file system.
End of explanation
"""


