February 23, 2016

RESTful Testing with Stripe: Storing API Keys in properties files and initial setup of StripeUtils

This post is third in a series of six. Need to go back to the beginning?

So far we covered why we should incorporate tests other than UI tests into our automation test suite. We gave a brief background on RESTful APIs. And we showed how to interact with the Stripe API through GET methods with HTTPS and POST methods with cURL.

Now, we can start writing code to interact with Stripe! We are going to:
  • Store the Stripe API Key in a properties file, pretending that the general purpose key is actually two different keys: One for the US and one for Canada.
  • Write a method to Load the Properties
  • Create a basic Stripe Utilities that forces the user to select which country we are using. Using that information the proper API key is loaded. 
  • Start writing a test class containing tests that confirm Stripe Utilities can only be instantiated if and only if the country is either US or Canada. 

What Our Framework Will Look Like



By the end of this blog post, our automated test framework will look something like this:

src/test/java
  • data
    • LoadProperties.java
  • libraries
    • StripeUtils.java
  • properties
    • qa-properties.properties
  • testcases
    • Stripe.java

First, let's talk about storing the keys in properties files.


What is a .properties file?

We are going to store the Stripe API Key for the general public in a properties file... But what is a properties file?

A Properties file is just a plain ole text file with the extension ".properties" after it.
".properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application. They can also be used for storing strings for Internationalization and localization; these are known as Property Resource Bundles.

"Each parameter is stored as a pair of strings, one storing the name of the parameter (called the key), and the other storing the value". - Wikipedia, .properties 
. . .
"Properties is a subclass of Hashtable. It is used to maintain lists of values in which the key is a String and the value is also a String.

"The Properties class is used by many other Java classes. For example, it is the type of object returned by System.getProperties( ) when obtaining environmental values [...]"
- TutorialsPoint, Java Properties 

How Do We Implement It?

StackOverflow, Loading a Properties File From a Java Package:
"When loading the Properties from a Class in the package com.al.common.email.templates you can use"
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream("foo.properties");
prop.load(in);
in.close();
"(Add all the necessary exception handling).
"If your class is not in that package, you need to aquire the InputStream slightly differently:
InputStream in = 
 getClass().getResourceAsStream("/com/al/common/email/templates/foo.properties");
"Relative paths (those without a leading '/') in getResource()/getResourceAsStream() mean that the resource will be searched relative to the directory which represents the package the class is in.

"Using java.lang.String.class.getResource("foo.txt") would search for the (inexistent) file /java/lang/String/foo.txt on the classpath.

"Using an absolute path (one that starts with '/') means that the current package is ignored".


Store the Stripe API Key


We can see in the Stripe API documentation at https://stripe.com/docs/api#intro that in the cURL statement used to hit their endpoint...

curl https://api.stripe.com/v1/charges \ -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: 

... the Stripe API Key for the general public is sk_test_BQokikJOvBiI2HlWgH4olfQ2.

That means that our properties file would look like this:

properties/qa-properties.properties
 # Stripe Public API key 
 stripe.api.key=sk_test_BQokikJOvBiI2HlWgH4olfQ2  
 stripe.api.version=2015-10-01  

How to Read the Properties File

We are going to create a class called LoadProperties to handle fetching the properties data.

LoadProperties method (private):
  • Create a static method loadProperties, pointing to where the qa-properties.properties file is located. 
  • Instantiate a new Properties object, from a class built into Java 7.
  • Attempt to load the file located at the filepath, catching any errors such as if the file is not there, or there is some  Input / Output error opening or closing the file. 
  • If there are any errors, print a stack trace. 
  • If there aren't any errors, read the file's contents in a FileInputStream called "f", the load the contents into properties.
  • Read the entire file, line by line. 
Once this method is created, we can have a public method, qaData, call this private method. 

data/LoadProperties.java
 public class LoadProperties {  
   public static Properties qaData = loadProperties("src/test/java/properties/qa-properties.properties");  
   private static Properties loadProperties(String filePath) {  
     Properties properties = new Properties();  
     try {  
       FileInputStream f = new FileInputStream(filePath);  
       properties.load(f);  
     } catch (FileNotFoundException e) {  
       e.printStackTrace();  
     } catch (IOException e) {  
       e.printStackTrace();  
     }  
     return properties;  
   }  
   public static String getPropertyValue(String path, String key) {  
     Properties p = loadProperties(path);  
     String result = "";  
     Set<String> values = p.stringPropertyNames();  
     for (String value : values) {  
       if (StringUtils.equalsIgnoreCase(value, key)) {  
         result = p.getProperty(value);  
         break;  
       }  
     }  
     return result;  
   }  
 }  


The Stripe Utilities class

The only acceptable country is "Locale.US". We are going to force everything else to fail.

 package libraries;  
 import com.stripe.Stripe;  
 import data.LoadProperties;  
 import org.testng.TestException;  
 import org.testng.annotations.Test;  
 import java.util.Locale;  
 /**  
  * Created by tmaher on 2/16/2016.  
  */  
 public class StripeUtils {  
   private static String getAPIKey() {  
     return Stripe.apiKey = LoadProperties.qaData.get("stripe.api.key").toString();  
   }  
   private static String getAPIVersion() {  
     return Stripe.apiVersion = LoadProperties.qaData.get("stripe.api.version").toString();  
   }  
   private static void getAPIKey(Locale country) {  
     getAPIVersion();  
     if (country.equals(Locale.US)) {  
       getAPIKey();  
     } else {  
       throw new TestException("ERROR: Stripe is used only for US. Country entered: " + country);  
     }  
   }  
   public StripeUtils(Locale country) {  
     getAPIKey(country);  
   }  
   private static StripeUtils setAPIKey(Locale country) {  
     return new StripeUtils(country);  
   }  
 }  

Test Early. Test Often. 

Let's create a folder called testcases, and place in it a test class, Stripe.java.

testcases.Stripe.java:
 package testcases;  
 import libraries.StripeUtils;  
 import org.testng.annotations.Test;  
 import java.util.Locale;  
 /**  
  * Created by tmaher on 2/16/2016.  
  */  
 public class Stripe {  
   @Test  
   public void test_validCountry() {  
     StripeUtils stripe = new StripeUtils(Locale.US);  
     // This will always pass.  
   }  
   @Test  
   public void test() {  
     StripeUtils stripe = new StripeUtils(Locale.GERMANY);  
     // This will always fail: ERROR: Stripe is used only for US. Country entered: de_DE   
   }  
 }  

Our test automation structure is starting to be built!

With the next blog post, we will be getting into using UriBuilder, HttpGet and other Apache HttpComponents.

Until next time, Happy Testing!

NEXT: UriBuilder, HttpGet and other Apache HttpComponents



-T.J. Maher
 Sr. QA Engineer, Fitbit
 Boston, MA

// Automated tester for [ 11 ] month and counting!

Please note: 'Adventures in Automation' is a personal blog about automated testing. It is not an official blog of Fitbit.com


1 comment:

Elise Hilton said...

Excellent post on handling API keys and configuring StripeUtils! Storing API keys in properties files is an excellent approach to keep them secure and organized; however, keep such files out of version control to avoid unintentional disclosure. Your advice on the initial setup of StripeUtils is also spot on; clear stages make integration simple. Those working on comparable projects should keep in mind that btec assignment help can provide additional insights and support to help them streamline their development processes.