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
1 2 |
requests==2.8.1 validators==0.9 |
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# -*- 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() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# -*- 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) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#!/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
1 2 3 4 5 |
# set access permissions $ chmod u+x ./RESTme.py # start application $ python -B ./RESTme.py |
The application should look like: