This time i want show you how to create your own REST testing application. For this demonstration i use Python, Tkinter and some Python libraries. At the end of this tutorial you can extend the application with more features like “show headers”, “store requests/responses”, “run automatically” and so on.
Preparation
- install Python > 2.7 (Tkinter included)
- install Requests: HTTP for Humans
- install Python Data Validation for Humans
requests==2.8.1 validators==0.9
Example
# -*- coding: utf-8 -*- from Tkinter import Tk, FALSE class BaseTkGui(object): """Define basic TK GUI""" def __init__(self, window_title, window_resizable): """Constructor for Tkinter GUI""" self._root = Tk() self._root.title(str(window_title)) if not bool(window_resizable): self._root.resizable(width=FALSE, height=FALSE) else: self._root.columnconfigure(0, weight=1) self._root.rowconfigure(0, weight=1) def start_app(self): """Start TK loop""" self._root.mainloop() def quit_app(self): """Stop and quit application""" self._root.quit()
# -*- coding: utf-8 -*- from Tkinter import (Frame, OptionMenu, Entry, Button, StringVar, Label, W, E, NO, END, SOLID) from ttk import Treeview, Separator from ScrolledText import ScrolledText from BaseGui import BaseTkGui class ApplicationTkGui(BaseTkGui): """Define application TK GUI""" OPTIONS = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] def __init__(self, window_title): """Constructor for specific application GUI""" BaseTkGui.__init__(self, window_title, False) self._method = None self._url = None self._tree = None self._status = None self._time = None self._key = None self._value = None self._output = None def build_frames(self): """Add all frames and start mainloop""" self.__top_frame() self.__middle_frame() self.__bottom_frame() self.start_app() def prepare_req(self): """Overwritten method""" pass def _add_items(self): """Add items into TreeView at end""" key = str(self._key.get()) value = str(self._value.get()) if key and value: self._tree.insert("", "end", values=(key, value)) self._key.delete(0, END) self._value.delete(0, END) self._tree.bind("<Double-1>", self._delete_item) def _delete_item(self, event): """Delete items from TreeView by ID""" item = self._tree.identify_row(event.y) self._tree.delete(item) def __top_frame(self): """Top frame creator""" self._method = StringVar(self._root) self._method.set("GET") frame = Frame(self._root) frame.grid(column=0, row=0, sticky=W+E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) option = OptionMenu(frame, self._method, *self.OPTIONS) option.grid(column=0, row=0, padx=5, pady=5) self._url = Entry(frame, width=50) self._url.grid(column=1, row=0, padx=5, pady=5) self._url.configure(borderwidth=1, relief=SOLID) self._url.configure(highlightthickness=0) self._url.insert(0, 'http://') submit = Button(frame, text='Submit', command=self.prepare_req) submit.grid(column=3, row=0, padx=5, pady=5) Separator(frame).grid(columnspan=4, row=1, sticky=W+E) def __middle_frame(self): """Middle frame creator""" frame = Frame(self._root) frame.grid(column=0, row=1, sticky=W+E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) self._tree = Treeview(frame, columns=("Key", "Val"), selectmode='none') self._tree.grid(columnspan=5, row=0, padx=5, pady=5, sticky=W+E) self._tree.column('#0', stretch=NO, minwidth=0, width=0) self._tree.heading('#1', text='Key') self._tree.heading('#2', text='Value') self._tree.configure(height=5) key = Label(frame, text='Key:') key.grid(column=0, row=1, padx=5, pady=5, sticky=E) self._key = Entry(frame) self._key.grid(column=1, row=1, padx=5, pady=5, sticky=W) self._key.configure(borderwidth=1, relief=SOLID) self._key.configure(highlightthickness=0) value = Label(frame, text='Value:') value.grid(column=2, row=1, padx=5, pady=5, sticky=E) self._value = Entry(frame) self._value.grid(column=3, row=1, padx=5, pady=5, sticky=W) self._value.configure(borderwidth=1, relief=SOLID) self._value.configure(highlightthickness=0) add = Button(frame, text='Add new header', command=self._add_items) add.grid(column=4, row=1, padx=5, pady=5) Separator(frame).grid(columnspan=5, row=2, sticky=W+E) def __bottom_frame(self): """Bottom frame creator""" font_style = ('verdana', 10, 'normal') frame = Frame(self._root) frame.grid(column=0, row=2, sticky=W+E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) self._status = Label(frame, text='Response Status: -') self._status.grid(column=0, row=0, sticky=W) self._status.configure(fg='red', font=font_style) self._time = Label(frame, text='Time: - ms') self._time.grid(column=1, row=0, sticky=E) self._time.configure(fg='red', font=font_style) self._output = ScrolledText(frame) self._output.grid(columnspan=2, row=1, padx=5, pady=5, sticky=W+E) self._output.configure(height=12, borderwidth=1, relief=SOLID) self._output.configure(highlightthickness=0)
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests import validators from Tkinter import END from ApplicationGui import ApplicationTkGui class Application(ApplicationTkGui): """Define application behaviors""" def __init__(self, window_title): """Constructor for application with title""" ApplicationTkGui.__init__(self, window_title) def run_application(self): """Start application""" self.build_frames() def prepare_req(self): """Prepare and validate request""" headers = dict() method = self._method.get() url = self._url.get() tree_ids = self._tree.get_children() for i in tree_ids: row = self._tree.item(i) add = row['values'] headers[add[0]] = add[1] if validators.url(url): self.__do_request(method, url, headers) def __do_request(self, method, url, headers): """Do request and print results""" self._output.delete(1.0, END) ses = requests.Session() prepped = requests.Request(method, url, headers).prepare() response = ses.send(prepped, verify=False, allow_redirects=True) code = response.status_code body = response.text time_delta = response.elapsed duration = time_delta.total_seconds() status = 'Response Status: ' + str(code) time = 'Time: ' + str(duration) + ' ms' text = body[0:900] + ' ...' self._status.configure(text=status) self._time.configure(text=time) self._output.insert(END, text) if __name__ == '__main__': RUN = Application('HTTPTester') RUN.run_application()
Run application
# set access permissions $ chmod u+x ./RESTme.py # start application $ python -B ./RESTme.py
The application should look like: