ht

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2015 License: BSD-3-Clause Imports: 42 Imported by: 12

Documentation

Overview

Package ht provides functions for easy testing of HTTP based protocols.

Testing is done by constructing a request, executing the request and performing various checks on the returned response. The type Test captures this idea. Each Test may contain an arbitrary list of Checks which perform the actual validation work. Tests can be grouped into Suites which may provide a common cookie jar for their tests and may execute setup and teardown actions.

All elements like Checks, Request, Tests and Suites are organized in a way to allow easy deserialisation from a text format. This allows to load and execute whole Suites at runtime.

Checks

A typical check validates a certain property of the received response. E.g.

StatusCode{Expect: 302}
Body{Contains: "foobar"}
Body{Contains: "foobar", Count: 2}
Body{Contains: "illegal", Count: -1}

The last three examples show how zero values of optional fields are commonly used: The zero value of Count means "any number of occurences". Forbidding the occurenc of "foobar" thus requires a negative Count.

The following checks are provided

  • StatusCode checks the received HTTP status code
  • ResponseTime provides lower and higer bounds on the response time
  • Header checks presence and values of received HTTP header
  • SetCookie checks properties of received cookies
  • Identity checks the SHA1 hash of the HTTP body
  • UTF8Encoded checks that the HTTP body is UTF-8 encoded
  • Body text lookup in the HTTP body
  • HTMLContains checks occurence HTML elements choosen via CSS-selectors
  • HTMLContainsText checks text content of CSS-selected elements
  • W3CValidHTML checks if body parses as valid HTML5
  • Links make sure hrefs and srcs in HTML are accessible
  • Image checks image format, size and content
  • JSON checks structure and content of a JSON body
  • XML checks elements of a XML body

Requests

Requests allow to specify a HTTP request in a declarative manner. A wide varity of request can be generated from a purly textual representation of the Request.

All the ugly stuff like parameter encoding, generation of multipart bodies, etc. are hidden from the user.

Parametrisations

Hardcoding e.g. the hostname in a test has obvious drawbacks. To overcome these the Request and Checks may be parametrised. This is done by a simple variable expansion in which occurences of variables are replaced by their values. Variables may occur in all (exported) string fields of Checks and all suitable string fields of Request in the form:

{{VARNAME}}

The variable substitution is performed during compilation of a Test which includes compilation of the embeded Checks.

The current time with an optional offset can be substituted by a special construct:

{{NOW}}                       -->  Wed, 01 Oct 2014 12:22:36 CEST
{{NOW + 15s}}                 -->  Wed, 01 Oct 2014 12:22:51 CEST
{{NOW + 25m | "15:04"}}       -->  12:47
{{NOW + 3d | "2006-Jan-02"}}  -->  2014-Oct-04

Formating the time is done with the usual reference time of package time and defaults to RFC1123. Offset can be negative, the known units are "s" for seconds, "m" for minutes, "h" for hours and "d" for days.

TODO: Add {RAND,UNIQUE}{INT,ID,WORDS} or something similiar.

Tests

A Test is basically just a Request combined with a list of Checks. Running a Test is executing the request and validating the response according to the Checks. Before a test can be run the variable substitution in the Request and the Checks have to happen, a real HTTP request has to be crafted and checks have to be set up. This is done by compiling the test, a step wich may fail: a) if the Request is malformed (e.g. uses a malformed URL) or b) if the checks are malformed (e.g. uses a malformed regexp). Such Tests/Checks are labeled Bogus.

There are three ways in which a Tests may fail:

  1. The test setup is malformed, such tests are called Bogus.
  2. The request itself fails. This is called an Error
  3. Any of the checks fail. This is called a Failure

Unrolling a Test

A common szenario is to do a test/check combination several times with tiny changes, e.g. a search with different queries. To facilliate writing these repeated tests it is possible to treat a Test as a template which is instantiated with different parametrizations. This process is called unrolling. The field UnrollWith of a test controlls this unrolling: It is a map of variabe names to variable values. The simplest definition is

UnrollWith: map[string][]string{"query": {"foo", "bar", "wuz"}}

with the test and probably the checks too containing references to the query variabel like "{{query}}". Unrolling such a test produces three different, new test, one with all occurences of "{{query}}" replaced by "foo", one with "bar" as the replacement and a third with "wuz". The unrolled tests do no longer contain the "{{query}}" variabel. If more than one variable is used during unrolling the situation is simple if both value sets have the same size: Variable substitution will use the first values first, then the second values and so on. If the variable have different length value sets e.g.

UnrollWith: map[string][]string{
    "a": {"1", "2", "3"},
    "b": {"x", "y"},
}

one would get 6 = 3*2 = the least common multiple of all value set length tests wit the first test having (a=1 b=x),the second one (a=2, b=y), the third one (a=3 b=x), and so on until the last one which has (a=3 b=y).

It is important to understand that Unrolling a Test produces several distinct Tests.

Suites of tests

Normaly tests are not run individually but grouped into suites. Such suite may share a common cookie jar (and a common logger) and may contain setup and teardown actions. Any action on a Suite normaly requires its setup tests to pass, afterwards the main tests are executed and finaly the teardown tests are run (but no errors or failures are reported for teardown tests).

Package response provides a type for captuiring a HTTP response. Its main purpose is breaking an import cycle between ht and ht/check.

Index

Constants

This section is empty.

Variables

View Source
var (
	BadBody        = errors.New("skipped due to bad body")
	Failed         = errors.New("failed")
	NotFound       = errors.New("not found")
	FoundForbidden = errors.New("found forbidden")
)
View Source
var (
	// DefaultUserAgent is the user agent string to send in http requests
	// if no user agent header is specified explicitely.
	DefaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"

	// DefaultAccept is the accept header to be sent if no accept header
	// is set explicitely in the test.
	DefaultAccept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"

	// DefaultClientTimeout is the timeout used by the http clients.
	DefaultClientTimeout = Duration(10 * time.Second)
)
View Source
var (
	TestTmpl      *template.Template
	SuiteTmpl     *template.Template
	HtmlSuiteTmpl *htmltemplate.Template
)
View Source
var CheckRegistry map[string]reflect.Type = make(map[string]reflect.Type)

CheckRegistry keeps track of all known Checks.

Functions

func BoldBox

func BoldBox(title string, prefix string) string

BoldBox around title, indented by prefix.

#################
##             ##
##    Title    ##
##             ##
#################

func Box

func Box(title string, prefix string) string

Box around title, indented by prefix.

+------------+
|    Title   |
+------------+

func MarshalCheck

func MarshalCheck(c Check) ([]byte, error)

func NameOf

func NameOf(check Check) string

NameOf returns the name of the check.

func RTHistogram

func RTHistogram(title string, data map[string][]int, dodge bool, filename string) error

RTHistogram produces a png file containing a histogram of the int values in data. Several histograms can be plotted, the keys of data are the labels. If dodge is true the histogram bars are not stacked.

func RegisterCheck

func RegisterCheck(check Check)

RegisterCheck registers the check. Once a check is registered it may be unmarshaled from its name and marshaled data.

func ToUpper

func ToUpper(s string) string

func Underline

func Underline(title string, c string, prefix string) string

Underline title with c, indented by prefix.

Title
~~~~~

Types

type Body

type Body Condition

func (Body) Execute

func (b Body) Execute(t *Test) error

func (*Body) Prepare

func (b *Body) Prepare() error

type CantCheck

type CantCheck struct {
	// contains filtered or unexported fields
}

CantCheck is the error type returned by checks whose preconditions are not fulfilled, e.g. malformed HTML or XML.

func (CantCheck) Error

func (m CantCheck) Error() string

type Check

type Check interface {
	// Prepare is called to prepare the check, e.g. to compile
	// regular expressions or that like.
	Prepare() error

	// Execute executes the check.
	Execute(*Test) error
}

Check is a single check performed on a Response.

func CreateCheck

func CreateCheck(name string, data []byte) (Check, error)

CreateCheck constructs the Check name from data.

func SubstituteVariables

func SubstituteVariables(check Check, r *strings.Replacer, f map[int64]int64) Check

SubstituteVariables returns a deep copy of check with all exported string fields in check modified by applying r and all int and int64 fields modified by applying f. TODO: applying r is not "variable replacing"

func UnmarshalCheck

func UnmarshalCheck(data []byte) (Check, error)

type CheckList

type CheckList []Check

CheckList is a slice of checks with the sole purpose of attaching JSON (un)marshaling methods.

func (CheckList) MarshalJSON

func (cl CheckList) MarshalJSON() ([]byte, error)

TODO: handle errors

func (*CheckList) UnmarshalJSON

func (cl *CheckList) UnmarshalJSON(data []byte) error

type CheckResult

type CheckResult struct {
	Name     string   // Name of the check as registered.
	JSON     string   // JSON serialization of check.
	Status   Status   // Outcome of check. All status but Error
	Duration Duration // How long the check took.
	Error    error    // For a Status of Bogus or Fail.
}

CheckResult captures the outcom of a single check inside a test.

type ClientPool

type ClientPool struct {
	// Transport will be used a the clients Transport
	Transport http.RoundTripper

	// Jar will be used as the clients Jar
	Jar http.CookieJar
	// contains filtered or unexported fields
}

ClientPool maintains a pool of clients for the given transport and cookie jar. ClientPools must not be copied.

func (*ClientPool) Get

func (p *ClientPool) Get(timeout Duration, followRedirects bool) *http.Client

Get retreives a new or existing http.Client for the given timeout and redirect following policy.

type Condition

type Condition struct {
	// Equals is the exact value to be expected.
	// No other tests are performed if Equals is non-zero as these
	// other tests would be redundant.
	Equals string `json:",omitempty"`

	// Prefix is the required prefix
	Prefix string `json:",omitempty"`

	// Suffix is the required suffix.
	Suffix string `json:",omitempty"`

	// Contains must be contained in the string.
	Contains string `json:",omitempty"`

	// Regexp is a regular expression to look for.
	Regexp string `json:",omitempty"`

	// Count determines how many occurences of Contains or Regexp
	// are required for a match:
	//     0: Any positive number of matches is okay
	//   > 0: Exactly that many matches required
	//   < 0: No match allowed (invert the condition)
	Count int `json:",omitempty"`

	// Min and Max are the minimum and maximum length the string may
	// have. Two zero values disables this test.
	Min, Max int `json:",omitempty"`
	// contains filtered or unexported fields
}

Condition is a cunjunction of tests against a string. Note that Contains and Regexp conditions both use the same Count; most likely one would use either Contains or Regexp but not both.

func (*Condition) Compile

func (c *Condition) Compile() (err error)

func (Condition) Fullfilled

func (c Condition) Fullfilled(s string) error

Fullfilled returns whether s matches all requirements of c. A nil return value indicates that s matches the defined conditions. A non-nil return indicates missmatch.

func (Condition) FullfilledBytes

func (c Condition) FullfilledBytes(b []byte) error

FullfilledBytes provides a optimized version for Fullfilled(string(byteSlice)). TODO: Make this a non-lie.

type Cookie struct {
	Name  string
	Value string `json:",omitempty"`
}

Cookie.

type Duration

type Duration time.Duration

Duration is a time.Duration but has nicer JSON encoding.

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

func (Duration) String

func (d Duration) String() string

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(data []byte) error

type Extractor

type Extractor struct {
	// HTMLElementSelector is the CSS selector of an element, e.g.
	//     head meta[name="_csrf"]   or
	//     form#login input[name="tok"]
	//     div.token > span
	HTMLElementSelector string

	// HTMLElementAttribute is the name of the attribute from which the
	// value should be extracted.  The magic value "~text~" refers to the
	// text content of the element. E.g. in the examples above the following
	// should be sensible:
	//     content
	//     value
	//     ~text~
	HTMLElementAttribute string
}

Extractor allows to extract data from an executed Test. It supports extracting HTML attribute values and HTML text node values. Support for different stuff like HTTP Header, JSON values, etc. are a major TODO. Examples for CSRF token in the HTML:

<meta name="_csrf" content="18f0ca3f-a50a-437f-9bd1-15c0caa28413" />
<input type="hidden" name="_csrf" value="18f0ca3f-a50a-437f-9bd1-15c0caa28413"/>

func (Extractor) Extract

func (e Extractor) Extract(t *Test) (string, error)

type HTMLContains

type HTMLContains struct {
	// Selector is the CSS selector of the HTML elements.
	Selector string

	// Count determines the number of occurences to check for:
	//     < 0: no occurence
	//    == 0: one ore more occurences
	//     > 0: exactly that many occurences
	Count int `json:",omitempty"`
	// contains filtered or unexported fields
}

HTMLContains checks for the existens of HTML elements selected by CSS selectors.

func (*HTMLContains) Execute

func (c *HTMLContains) Execute(t *Test) error

func (*HTMLContains) Prepare

func (c *HTMLContains) Prepare() (err error)

type HTMLContainsText

type HTMLContainsText struct {
	// Selector is the CSS selector of the HTML elements.
	Selector string

	// The plain text content of each selected element.
	Text []string `json:",omitempty"`

	// Raw turns of white space normalization and returns the unprocessed
	// text content.
	Raw bool `json:",omitempty"`

	// If true: Text contains all matches of Selector.
	Complete bool `json:",omitempty"`
	// contains filtered or unexported fields
}

HTMLContainsText check the text content off HTML elements selected by a CSS rule.

The text content found in the HTML document is normalized by roughly the following procedure:

  1. Newlines are inserted around HTML block elements (actuall any non-inline element)
  2. Newlines and tabs are replaced by spaces.
  3. Multiple spaces are replaced by one space.
  4. Leading and trailing spaces are trimmed of.

As an example consider the following HTML:

<html><body>
  <ul class="fancy"><li>One</li><li>S<strong>econ</strong>d</li><li> Three </li></ul>
</body></html>

The normalized text selected by a Selector of "ul.fancy" would be

"One Second Three"

func (*HTMLContainsText) Execute

func (c *HTMLContainsText) Execute(t *Test) error

func (*HTMLContainsText) Prepare

func (c *HTMLContainsText) Prepare() (err error)
type Header struct {
	// Header is the HTTP header to check.
	Header string

	// Condition is applied to the first header value. A zero value checks
	// for the existence of the given Header only.
	Condition `json:",omitempty"`

	// Absent indicates that no header Header shall be part of the response.
	Absent bool `json:",omitempty"`
}

Header provides a textual test of single-valued HTTP headers.

func (Header) Execute

func (h Header) Execute(t *Test) error

func (*Header) Prepare

func (h *Header) Prepare() error

type Identity

type Identity struct {
	// SHA1 is the expected hash as shown by sha1sum of the whole body.
	// E.g. 2ef7bde608ce5404e97d5f042f95f89f1c232871 for a "Hello World!"
	// body (no newline).
	SHA1 string
}

Identity checks the value of the response body by comparing its SHA1 hash to the expacted has value.

func (Identity) Execute

func (i Identity) Execute(t *Test) error

Execute implements Checks Execute method.

func (Identity) Prepare

func (_ Identity) Prepare() error

Prepare implements Checks Prepare method.

type Image

type Image struct {
	// Format is the format of the image as registered in package image.
	Format string `json:",omitempty"`

	// If > 0 check width or height of image.
	Width, Height int `json:",omitempty"`

	// Fingerprint is either the 16 hex digit long Block Mean Value hash or
	// the 24 hex digit long Color Histogram hash of the image.
	Fingerprint string `json:",omitempty"`

	// Threshold is the limit up to which the received image may differ
	// from the given BMV or ColorHist fingerprint.
	Threshold float64 `json:",omitempty"`
}

Image checks image format, size and fingerprint. As usual a zero value of a field skipps the check of that property. Image fingerprinting is done via github.com/vdobler/ht/fingerprint. Only one of BMV or ColorHist should be used as there is just one threshold.

func (Image) Execute

func (c Image) Execute(t *Test) error

func (Image) Prepare

func (i Image) Prepare() error

type JSON

type JSON struct {
	// Expression is a boolean gojee expression which must evaluate
	// to true for the check to pass.
	Expression string
	// contains filtered or unexported fields
}

JSON checking via github.com/nytlabs/gojee

func (*JSON) Execute

func (c *JSON) Execute(t *Test) error

func (*JSON) Prepare

func (c *JSON) Prepare() (err error)
type Links struct {
	// Head triggers HEAD request instead of GET requests.
	Head bool

	// Which links to test; a combination of "a", "img", "link" and "script".
	// E.g. use "a img" to check the href of all a-tags and src of all img-tags.
	Which string

	// Concurrency determines how many of the found links are checked
	// concurrently. A zero value indicats sequential checking.
	Concurrency int `json:",omitempty"`

	// Timeout if different from main test.
	Timeout Duration `json:",omitempty"`

	IgnoredLinks []Condition `json:",omitempty"`
	// contains filtered or unexported fields
}

Links checks links and references in HTML pages for availability

func (*Links) Execute

func (c *Links) Execute(t *Test) error

func (*Links) Prepare

func (c *Links) Prepare() (err error)

type LoadTestOptions

type LoadTestOptions struct {
	// Type determines wether a "throughput" or "concurrency" test is done.
	Type string

	// Count many request are made during the load test in total.
	Count int

	// Timout determines how long a test may run: The load test is
	// terminated if timeout is exeded, even if not Count many requests
	// heve been made yet.
	Timeout time.Duration

	// Rate is the average rate of requests in [request/sec].
	Rate float64

	// Uniform changes to uniform (equaly spaced) distribution of
	// requests. False uses an exponential distribution.
	Uniform bool
}

LoadTestOptions controls details of a load test.

type LoadtestResult

type LoadtestResult struct {
	Started  time.Time
	Total    int
	Passed   int
	Failed   int
	Errored  int
	Skipped  int
	Bogus    int
	PassHist *loghist.Hist
	FailHist *loghist.Hist
	BothHist *loghist.Hist
}

LoadtestResult captures aggregated values of a load test.

func AnalyseLoadtest

func AnalyseLoadtest(results []Test) LoadtestResult

AnalyseLoadtest computes aggregate statistics of the given results.

func (LoadtestResult) String

func (r LoadtestResult) String() string

String formats r in a useful way.

type MalformedCheck

type MalformedCheck struct {
	Err error
}

MalformedCheck is the error type returned by checks who are badly parametrized, e.g. who try to check against a malformed regular expression.

func (MalformedCheck) Error

func (m MalformedCheck) Error() string

type Poll

type Poll struct {
	// Maximum number of redos. Both 0 and 1 mean: "Just one try. No redo."
	// Negative values indicate that the test should be skipped.
	Max int `json:",omitempty"`

	// Duration to sleep between redos.
	Sleep Duration `json:",omitempty"`
}

Poll determines if and how to redo a test after a failure or if the test should be skipped alltogether. The zero value of Poll means "Just do the test once."

func (Poll) Skip

func (p Poll) Skip() bool

Skip return whether the test should be skipped.

type Request

type Request struct {
	// Method is the HTTP method to use.
	// A empty method is equivalent to "GET"
	Method string `json:",omitempty"`

	// URL ist the URL of the request.
	URL string

	// Params contains the parameters and their values to send in
	// the request.
	//
	// If the parameters are sent as multipart it is possible to include
	// files by letting the parameter values start with "@file:". Two
	// version are possible "@file:path/to/file" will send a file read
	// from the given filesystem path while "@file:@name:the-file-data"
	// will use the-file-data as the content.
	Params URLValues `json:",omitempty"`

	// ParamsAs determines how the parameters in the Param field are sent:
	//   "URL" or "": append properly encoded to URL
	//   "body"     : send as application/x-www-form-urlencoded in body.
	//   "multipart": send as multipart in body.
	// The two values "body" and "multipart" must not be used
	// on a GET or HEAD request.
	ParamsAs string `json:",omitempty"`

	// Header contains the specific http headers to be sent in this request.
	// User-Agent and Accept headers are set automaticaly to the global
	// default values if not set explicitely.
	Header http.Header `json:",omitempty"`

	// Cookies contains the cookies to send in the request.
	Cookies []Cookie `json:",omitempty"`

	// Body is the full body to send in the request. Body must be
	// empty if Params are sent as multipart or form-urlencoded.
	Body string `json:",omitempty"`

	// FollowRedirects determines if automatic following of
	// redirects should be done.
	FollowRedirects bool `json:",omitempty"`

	Request  *http.Request // the 'real' request
	SentBody string        // the 'real' body
}

Request is a HTTP request.

type Response

type Response struct {
	// Response is the received HTTP response. Its body has bean read and
	// closed allready.
	Response *http.Response

	// Duration to receive response and read the whole body.
	Duration Duration

	// The received body and the error got while reading it.
	BodyBytes []byte
	BodyErr   error
}

Response captures information about a http response.

func (*Response) Body

func (resp *Response) Body() *bytes.Reader

Body returns a reader of the response body.

type ResponseTime

type ResponseTime struct {
	Lower  Duration `json:",omitempty"`
	Higher Duration `json:",omitempty"`
}

ResponseTime checks the response time.

func (ResponseTime) Execute

func (c ResponseTime) Execute(t *Test) error

func (ResponseTime) Prepare

func (_ ResponseTime) Prepare() error

type SetCookie

type SetCookie struct {
	Name   string    `json:",omitempty"` // Name is the cookie name.
	Value  Condition `json:",omitempty"` // Value is applied to the cookie value
	Path   Condition `json:",omitempty"` // Path is applied to the path value
	Domain Condition `json:",omitempty"` // Domain is applied to the domain value

	// MinLifetime is the expectetd minimum lifetime of the cookie.
	MinLifetime time.Duration `json:",omitempty"`

	// Absent indicates that the cookie with the given Name must not be received.
	Absent bool `json:",omitempty"`
}

SetCookie checks for cookies beeing properly set. Note that the Path and Domain conditions are checked on the received Path and/or Domain and not on the interpreted values according to RFC 6265.

func (SetCookie) Execute

func (c SetCookie) Execute(t *Test) error

func (*SetCookie) Prepare

func (c *SetCookie) Prepare() error

type Status

type Status int

Status describes the status of a Test or a Check.

const (
	NotRun  Status = iota // Not jet executed
	Skipped               // Omitted deliberately
	Pass                  // That's what we want
	Fail                  // One ore more checks failed
	Error                 // Request or body reading failed (not for checks).
	Bogus                 // Bogus test or check (malformd URL, bad regexp, etc.)
)

func (Status) MarshalText

func (s Status) MarshalText() ([]byte, error)

func (Status) String

func (s Status) String() string

type StatusCode

type StatusCode struct {
	Expect int `xml:",attr"`
}

StatusCode checks the HTTP statuscode.

func (StatusCode) Execute

func (c StatusCode) Execute(t *Test) error

func (StatusCode) Prepare

func (_ StatusCode) Prepare() error

type Suite

type Suite struct {
	Name        string
	Description string

	// Test contains the actual tests to execute.
	Tests []*Test

	// OmitChecks allows to omit all checks defined on the main tests.
	OmitChecks bool

	// Setup contain tests to be executed before the execution actual tests.
	// If one or more setup test fail, the main tets won't be executed.
	// Teardown tests are excuted after the main test.
	// Setup and Teardown share the cookie jar with the main tests.
	Setup, Teardown []*Test

	// Variables contains global variables to be used during this
	// execution
	Variables map[string]string

	// KeepCookies determines whether to use a cookie jar to keep
	// cookies between tests.
	KeepCookies bool

	// Log is the logger to be used by tests and checks.
	Log *log.Logger

	// Populated during execution
	Status   Status
	Error    error
	Started  time.Time
	Duration Duration
}

A Suite is a collection of tests which are run together. A Suite must be prepared before it can be executed or Executes concurrently.

func LoadSuite

func LoadSuite(filename string) (*Suite, error)

LoadSuite reads a suite from filename. Tests and mixins are read relative to the directory the suite lives in.

func (Suite) AllTests

func (s Suite) AllTests() []*Test

func (*Suite) Execute

func (s *Suite) Execute()

Execute the whole suite sequentially.

func (*Suite) ExecuteConcurrent

func (s *Suite) ExecuteConcurrent(maxConcurrent int) error

ExecuteConcurrent executes all non-setup, non-teardown tests concurrently. But at most maxConcurrent tests of s are executed concurrently.

func (*Suite) ExecuteSetup

func (s *Suite) ExecuteSetup()

Execute the setup tests in s. The tests are executed sequentialy, execution stops on the first error.

func (*Suite) ExecuteTeardown

func (s *Suite) ExecuteTeardown()

ExecuteTeardown runs all teardown tests ignoring all errors.

func (*Suite) ExecuteTests

func (s *Suite) ExecuteTests()

Execute all non-setup, non-teardown tests of s sequentialy.

func (Suite) HTMLReport

func (s Suite) HTMLReport(dir string) error

func (*Suite) JUnit4XML added in v0.2.0

func (s *Suite) JUnit4XML() (string, error)

JUnit4XML generates a JUnit 4 compatible XML result with each Check reported as an individual testcase. NotRun checks are reported as Skipped and Bogus checks are counted as Errored tests.

func (*Suite) Prepare

func (s *Suite) Prepare() error

Prepare all tests in s for execution. This will also prepare all tests to detect bogus tests early.

func (Suite) PrintReport

func (r Suite) PrintReport(w io.Writer) error

func (*Suite) Stats

func (s *Suite) Stats() (notRun int, skipped int, passed int, failed int, errored int, bogus int)

Stats counts the test results of sr.

type Test

type Test struct {
	Name        string
	Description string

	// Request is the HTTP request.
	Request Request

	// Checks contains all checks to perform on the response to the HTTP request.
	Checks CheckList

	// VarEx may be used to popultate variables from the response.
	VarEx map[string]Extractor

	Poll      Poll     `json:",omitempty"`
	Timeout   Duration // If zero use DefaultClientTimeout.
	Verbosity int      // Verbosity level in logging.

	// Pre-, Inter- and PostSleep are the sleep durations made
	// before the request, between request and the checks and
	// after the checks.
	PreSleep, InterSleep, PostSleep Duration `json:",omitempty"`

	// ClientPool allows to inject special http.Transports or a
	// cookie jar to be used by this Test.
	ClientPool *ClientPool `json:"-"`

	Response Response

	// The following results are filled during Run.
	Status       Status        `json:"-"`
	Started      time.Time     `json:"-"`
	Error        error         `json:"-"`
	Duration     Duration      `json:"-"`
	FullDuration Duration      `json:"-"`
	Tries        int           `json:"-"`
	CheckResults []CheckResult `json:"-"` // The individual checks.

	SeqNo string
	// contains filtered or unexported fields
}

Test is a single logical test which does one HTTP request and checks a number of Checks on the recieved Response.

func LoadTest

func LoadTest(filename string) ([]*Test, error)

LoadTest reads a test from filename. Tests and mixins are read relative to the directory the test lives in. Unrolling is performed.

func Merge

func Merge(tests ...*Test) (*Test, error)

Merge merges all tests into one. The individual fields are merged in the following way.

Name         Join all names
Description  Join all descriptions
Request
  Method     All nonempty must be the same
  URL        Only one may be nonempty
  Params     Merge by key
  ParamsAs   All nonempty must be the same
  Header     Merge by key
  Cookies    Merge by cookie name
  Body       Only one may be nonempty
  FollowRdr  Last wins
Checks       Append all checks
VarEx        Merge, same keys must have same value
Poll
  Max        Use largest
  Sleep      Use largest
Timeout      Use largets
Verbosity    Use largets
PreSleep     Summ of all;  same for InterSleep and PostSleep
ClientPool   ignore

func PerformanceLoadTest

func PerformanceLoadTest(suites []*Suite, opts LoadTestOptions) ([]Test, error)

PerformanceLoadTest will perform a load test of the main tests of suites, the details of the load test is controlled by opts. Errors are reported if any suite's Setup failed.

func Repeat

func Repeat(test *Test, count int, vars map[string][]string) ([]*Test, error)

Repeat returns count copies of test with variables replaced based on vars. The keys of vars are the variable names. The values of a variable v are choosen from vars[v] by cycling through the list: In the n'th repetition is vars[v][n%N] with N=len(vars[v])).

func (*Test) Benchmark

func (t *Test) Benchmark(variables map[string]string, warmup int, count int, pause time.Duration, conc int) []Test

Benchmark executes t count many times and reports the outcome. Before doing the measurements warmup many request are made and discarded. Conc determines the concurrency level. If conc==1 the given pause is made between request. A conc > 1 will execute conc many request in paralell (without pauses). TODO: move this into an BenmarkOptions

func (*Test) Extract

func (t *Test) Extract() map[string]string

Extract all values defined by VarEx from the sucessfully executed Test t.

func (Test) PrintReport

func (t Test) PrintReport(w io.Writer) error

func (*Test) Run

func (t *Test) Run(variables map[string]string) error

Run runs the test t. The actual HTTP request is crafted and executed and the checks are performed on the received response. This whole process is repeated on failure or skipped entirely according to t.Poll.

The given variables are subsitutet into the relevant parts of the reuestt and the checks.

Normally all checks in t.Checks are executed. If the first check in t.Checks is a StatusCode check against 200 and it fails, then the rest of the tests are skipped.

Run returns a non-nil error only if the test is bogus; a failing http request, problems reading the body or any failing checks do not trigger a non-nil return value.

type URLValues

type URLValues url.Values

URLValues is a url.Values with a fancier JSON unmarshalling.

func (*URLValues) UnmarshalJSON

func (v *URLValues) UnmarshalJSON(data []byte) error

UnmarshalJSON produces a url.Values (i.e. a map[string][]string) from various JSON5 representations. E.g.

{
  a: 12,
  b: "foo",
  c: [ 23, "bar"]
}

can be unmarshaled with the expected result.

type UTF8Encoded

type UTF8Encoded struct{}

UTF8Encoded checks that the response body is valid UTF-8 without BOMs.

func (UTF8Encoded) Execute

func (c UTF8Encoded) Execute(t *Test) error

func (UTF8Encoded) Prepare

func (_ UTF8Encoded) Prepare() error

type ValidHTML

type ValidHTML struct{}

ValidHTML checks for valid HTML 5. Kinda: It never fails. TODO: make it useful.

func (ValidHTML) Execute

func (c ValidHTML) Execute(t *Test) error

func (ValidHTML) Prepare

func (_ ValidHTML) Prepare() error

type ValidationIssue

type ValidationIssue struct {
	Position string
	Message  string
	Input    string
}

ValidationIssue contains extracted information from the output of a W3C validator run.

type W3CValidHTML

type W3CValidHTML struct {
	// AllowedErrors is the number of allowed errors (after ignoring errors).
	AllowedErrors int `json:",omitempty"`

	// IgnoredErrros is a list of error messages to be ignored completely.
	IgnoredErrors []Condition `json:",omitempty"`
}

W3CValidHTML checks for valid HTML but checking the response body via the online checker from W3C which is very strict.

func (W3CValidHTML) Execute

func (w W3CValidHTML) Execute(t *Test) error

func (W3CValidHTML) Prepare

func (_ W3CValidHTML) Prepare() error

type WrongCount

type WrongCount struct {
	Got, Want int
}

WrongCount is the error type returned by checks which require a certain number of matches.

func (WrongCount) Error

func (m WrongCount) Error() string

type XML

type XML struct {
	// Path is a XPath expression understood by launchpad.net/xmlpath.
	Path string

	// Condition the first element addressed by Path must fullfill.
	Condition
	// contains filtered or unexported fields
}

XML allows to check XML request bodies.

func (*XML) Execute

func (x *XML) Execute(t *Test) error

func (*XML) Prepare

func (x *XML) Prepare() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL