Testing Class Material

This commit is contained in:
Lisa Schwetlick 2024-08-26 13:54:13 +02:00
commit 05b1f6cdd5
85 changed files with 102796 additions and 0 deletions

View file

@ -0,0 +1,8 @@
def times_3(x):
""" Multiply x by 3.
Parameters
----------
x : The item to multiply by 3.
"""
return x * 3

View file

@ -0,0 +1,28 @@
from first import times_3
def test_times_3_integer():
value = 7
expected = 21
result = times_3(value)
assert result == expected
def test_times_3_string():
value = 'wow'
expected = 'wowwowwow'
result = times_3(value)
assert result == expected
def test_times_3_list():
value = [1]
expected = [1, 1, 1]
result = times_3(value)
assert result == expected

View file

@ -0,0 +1,44 @@
def find_maxima(x):
"""Find local maxima of x.
Example:
>>> x = [1, 3, -2, 0, 2, 1]
>>> find_maxima(x)
[1, 4]
If in a local maximum several elements have the same value,
return the left-most index.
Example:
>>> x = [1, 2, 2, 1]
>>> find_maxima(x)
[1]
Input arguments:
x -- 1D list of real numbers
Output:
idx -- list of indices of the local maxima in x
"""
idx = []
up = False
down = False
for i in range(len(x)):
if i == 0 or x[i-1] < x[i]:
up = True
up_idx = i
elif x[i-1] > x[i]:
up = False
# if x[i-1] == x[i], no change
if i+1 == len(x) or x[i+1] < x[i]:
down = True
elif x[i+1] > x[i]:
down = False
if up and down:
idx.append(up_idx)
return idx

View file

@ -0,0 +1,36 @@
from local_maxima import find_maxima
def test_find_maxima():
values = [1, 3, -2, 0, 2, 1]
expected = [1, 4]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_edges():
values = [4, 2, 1, 3, 1, 5]
expected = [0, 3, 5]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_empty():
values = []
expected = []
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_plateau():
values = [1, 2, 2, 1]
expected = [1]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_not_a_plateau():
values = [1, 2, 2, 3, 1]
expected = [3]
maxima = find_maxima(values)
assert maxima == expected

View file

@ -0,0 +1,67 @@
import math
import numpy as np
def find_maxima(x):
"""Find local maxima of x.
Input arguments:
x -- 1D list of real numbers
Output:
idx -- list of indices of the local maxima in x
"""
maxima = []
len_x = len(x)
if len_x == 0:
return maxima
elif len_x == 1:
return [0]
# additional checks
if np.all([isinstance(item, str) for item in x]):
x = [item.lower() for item in x]
if np.all([item == x[0] for item in x]):
return [0]
maxima = check_first_element(x, maxima)
# Check numbers in between
i = 1
while i < len_x - 1:
if x[i] >= x[i - 1]:
# We have found a potential maximum or start of a plateau
# breakpoint()
if i == 1 and x[i] == x[i - 1]:
plateau_start = i - 1
else:
plateau_start = i
while i < len_x - 1 and x[i] == x[i + 1]:
i += 1
plateau_end = i
if plateau_end == len_x - 1:
maxima.append((plateau_end + plateau_start) // 2)
elif x[plateau_end] > x[plateau_end + 1]:
maxima.append((plateau_end + plateau_start) // 2)
i += 1
maxima = check_last_element(x, maxima)
return maxima
def check_first_element(x, maxima):
if x[0] > x[1]:
maxima.append(0)
return maxima
def check_last_element(x, maxima):
if x[-1] > x[-2]:
maxima.append(len(x) - 1)
return maxima
if __name__ == "__main__":
# result = find_maxima([1, 3, -2, 0, 2, 1])
result = find_maxima([1, 2, 2, 1])
print(result)

View file

@ -0,0 +1,97 @@
import numpy as np
import pytest
from local_maxima_solution import find_maxima
def test_find_maxima():
values = [1, 3, -2, 0, 2, 1]
expected = [1, 4]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_edges():
values = [4, 2, 1, 0, 1, 5]
expected = [0, 5]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_empty():
values = []
expected = []
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_plateau():
values = [1, 2, 2, 1]
expected = [1]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_not_a_plateau():
values = [1, 2, 2, 3, 1]
expected = [3]
maxima = find_maxima(values)
assert maxima == expected
# the tests below here fail, can you get them to pass?
def test_find_maxima_correct_order():
values = [2, 1, 5, 1, 9]
expected = [0, 2, 4]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_one_value():
values = [1]
expected = [0]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_long_plateau():
values = [1, 2, 2, 2, 2, 2, 1, 8, 0]
expected = [3, 7]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_plateau_at_end():
values = [1, 2, 2]
expected = [1]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_plateau_at_start():
values = [1, 1, 0, 0]
expected = [0]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_all_same_values():
values = [1, 1]
expected = [0]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_letters():
values = ["T", "e", "s", "t", "s", "!"]
expected = [0, 3]
maxima = find_maxima(values)
assert maxima == expected
def test_find_maxima_new_inputs_to_make_current_function_fail():
# should you actually be done with all tests, then you can think of other cases where the current function fails
# and write tests for them and fix them
assert True

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 KiB

View file

@ -0,0 +1,28 @@
import numpy as np
import pytest
# add a commandline option to pytest
def pytest_addoption(parser):
"""Add random seed option to py.test.
"""
parser.addoption('--seed', dest='seed', type=int, action='store',
help='set random seed')
# configure pytest to automatically set the rnd seed if not passed on CLI
def pytest_configure(config):
seed = config.getvalue("seed")
# if seed was not set by the user, we set one now
if seed is None or seed == ('NO', 'DEFAULT'):
config.option.seed = int(np.random.randint(2**31-1))
def pytest_report_header(config):
return f'Using random seed: {config.option.seed}'
@pytest.fixture
def random_state(request):
random_state = np.random.RandomState(request.config.option.seed)
return random_state

View file

@ -0,0 +1,10 @@
import numpy as np
import pytest
SEED = 42
@pytest.fixture
def random_state():
print(f'Seed: {SEED}')
random_state = np.random.RandomState(SEED)
return random_state

View file

@ -0,0 +1,25 @@
import numpy as np
def f(x, r):
"""
takes r and x as input and returns r*x*(1-x)
"""
return r * x * (1 - x)
def iterate_f(it, xi, r):
"""
takes a number of iterations `it`, a starting value,
and a parameter value for r. It should execute f repeatedly (it times),
each time using the last result of f as the new input to f. Append each
iteration's result to a list l. Finally, convert the list into a numpy
array and return it.
"""
x = xi
xs = []
for _ in range(it):
x = f(x, r)
xs.append(x)
return np.array(xs)

View file

@ -0,0 +1,70 @@
"""Usage:
```
plot_trajectory(100, 3.6, 0.1)
plot_bifurcation(2.5, 4.2, 0.001)
```
"""
import numpy as np
from matplotlib import pyplot as plt
from logistic import iterate_f
def plot_trajectory(n, r, x0, fname="single_trajectory.png"):
"""
Saves a plot of a single trajectory of the logistic function
inputs
n: int (number of iterations)
r: float (r value for the logistic function)
x0: float (between 0 and 1, starting point for the iteration)
fname: str (filename to which to save the image)
returns
fig, ax (matplotlib objects)
"""
l = iterate_f(n, x0, r)
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(list(range(n)), l)
fig.suptitle('Logistic Function')
fig.savefig(fname)
return fig, ax
def plot_bifurcation(start, end, step, fname="bifurcation.png", it=100000,
last=300):
"""
Saves a plot of the bifurcation diagram of the logistic function. The
`start`, `end`, and `step` parameters define for which r values to
calculate the logistic function. If you space them too closely, it might
take a very long time, if you dont plot enough, your bifurcation diagram
won't be informative. Choose wisely!
inputs
start, end, step: float (which r values to calculate the logistic
function for)
fname: str (filename to which to save the image)
it: int (how many iterations to run for each r value)
last: int (how many of the last iterates to plot)
returns
fig, ax (matplotlib objects)
"""
r_range = np.arange(start, end, step)
x = []
y = []
for r in r_range:
l = iterate_f(it, 0.1, r)
ll = l[len(l) - last::].copy()
lll = np.unique(ll)
y.extend(lll)
x.extend(np.ones(len(lll)) * r)
fig, ax = plt.subplots(figsize=(20, 10))
ax.scatter(x, y, s=0.1, color='k')
ax.set_xlabel("r")
fig.savefig(fname)
return fig, ax

View file

@ -0,0 +1,3 @@
from plot_logfun import plot_trajectory
plot_trajectory(100, 3.4, 0.1)

View file

@ -0,0 +1,81 @@
# Testing Project for ASPP 2023 Mexico
## Exercise 1 -- @parametrize and the logistic map
Make a file `logistic.py` and `test_logistic.py` in the same folder as this
readme and the `plot_logfun.py` file. Implement the code for the logistic map
in the `logistic.py` file:
a) Implement the logistic map f(𝑥)=𝑟𝑥(1𝑥) . Use `@parametrize`
to test the function for the following cases:
```
x=0.1, r=2.2 => f(x, r)=0.198
x=0.2, r=3.4 => f(x, r)=0.544
x=0.75, r=1.7 => f(x, r)=0.31875
```
b) Implement the function `iterate_f` that runs `f` for `it`
iterations, each time passing the result back into f.
Use `@parametrize` to test the function for the following cases:
```
x=0.1, r=2.2, it=1 => iterate_f(it, x, r)=[0.198]
x=0.2, r=3.4, it=4 => f(x, r)=[0.544, 0.843418, 0.449019, 0.841163]
x=0.75, r=1.7, it=2 => f(x, r)=[0.31875, 0.369152]
```
c) Import and call the `plot_trajectory` function from the `plot_logfun`
module to look at the trajectories generated by your code. The `plot_logfun`
imports and uses your `logistic.py` code. Import the module
and call the function in a new `plot_script.py` file.
Try with values `r<3`, `r>4` and `3<r<4` to get a feeling for how the function
behaves differently with different parameters. Note that your input x0 should
be between 0 and 1.
## Exercise 2 -- Check the convergence of an attractor using fuzzing
a) Write a numerical fuzzing test that checks that, for `r=1.5`, all
starting points converge to the attractor `f(x, r) = 1/3`.
b) Use `pytest.mark` to mark the tests from the previous exercise with one mark
(they relate to the correct implementation of the logistic map) and the
test from this exercise with another (relates to the behavior of the logistic
map). Try executing first the first set of tests and then the second set of
tests separately.
## Exercise 3 -- Chaotic behavior
Some r values for `3<r<4` have some interesting properties. A chaotic
trajectory doesn't diverge but also doesn't converge.
## Visualize the bifurcation diagram
a) Use the `plot_trajectory` function from the `plot_logfun` module using your
implementation of `f` and `iterate_f` to look at the bifurcation diagram.
The script generates an output image, `bifurcation_diagram.png`.
b) Write a test that checks for chaotic behavior when r=3.8. Run the
logistic map for 100000 iterations and verify the conditions for
chaotic behavior:
1) The function is deterministic: this does not need to be tested in
this case
2) Orbits must be bounded: check that all values are between 0 and 1
3) Orbits must be aperiodic: check that the last 1000 values are all
different
4) Sensitive dependence on initial conditions: this is the bonus
exercise below
The test should check conditions 2) and 3)!
## Bonus Exercise 4 -- The Butterfly Effect
For the same value of `r`, test the sensitive dependence on initial
conditions, a.k.a. the butterfly effect. Use the following definition of SDIC.
>`f` is a function and `x0` and `y0` are two possible seeds.
>If `f` has SDIC then:
>there is a number `delta` such that for any `x0` there is a `y0` that is not
>more than `init_error` away from `x0`, where the initial condition `y0` has
>the property that there is some integer n such that after n iterations, the
>orbit is more than `delta` away from the orbit of `x0`. That is
>|xn-yn| > delta

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View file

@ -0,0 +1,108 @@
import numpy as np
from numpy.testing import assert_allclose
import pytest
from logistic import f, iterate_f
# set the random seed for once here
SEED = np.random.randint(0, 2**31)
@pytest.fixture
def random_state():
print(f'Using seed {SEED}')
random_state = np.random.RandomState(SEED)
return random_state
@pytest.mark.parametrize('a', [1, 2, 3])
@pytest.mark.parametrize('b', [5, 6, 7])
def test_addition_increases(a, b):
print(a, b)
assert b + a > a
@pytest.mark.parametrize(
'x, r, expected',
[
(0.1, 2.2, 0.198),
(0.2, 3.4, 0.544),
(0.75, 1.7, 0.31875),
]
)
def test_f(x, r, expected):
result = f(x, r)
assert_allclose(result, expected)
@pytest.mark.parametrize(
'x, r, it, expected',
[
(0.1, 2.2, 1, [0.198]),
(0.2, 3.4, 4, [0.544, 0.843418, 0.449019, 0.841163]),
(0.75, 1.7, 2, [0.31875, 0.369152]),
]
)
def test_iterate_f(x, r, it, expected):
result = iterate_f(it, x, r)
assert_allclose(result, expected, rtol=1e-5)
def test_attractor_converges():
SEED = 42
random_state = np.random.RandomState(SEED)
for _ in range(100):
x = random_state.uniform(0, 1)
result = iterate_f(100, x, 1.5)
assert_allclose(result[-1], 1 / 3)
####################################################################
# These only work after adding the fixture
####################################################################
@pytest.mark.xfail
def test_attractor_converges2(random_state):
for _ in range(100):
x = random_state.uniform(0, 1)
result = iterate_f(100, x, 1.5)
assert_allclose(result[-1], 1 / 3)
@pytest.mark.xfail
def test_chaotic_behavior(random_state):
r = 3.8
for _ in range(10):
x = random_state.uniform(0, 1)
result = iterate_f(100000, x, r)
assert np.all(result >= 0.0)
assert np.all(result <= 1.0)
assert min(np.abs(np.diff(result[-1000:]))) > 1e-6
@pytest.mark.xfail
def test_sensitivity_to_initial_conditions(random_state):
"""
`f` is a function and `x0` and `y0` are two possible seeds.
If `f` has SDIC then:
there is a number `delta` such that for any `x0` there is a `y0` that is
not more than `init_error` away from `x0`, where the initial condition `y0`
has the property that there is some integer n such that after n iterations,
the orbit is more than `delta` away from the orbit of `x0`. That is
|xn-yn| > delta
"""
delta = 0.1
n = 10000
x0 = random_state.rand()
x0_diffs = random_state.rand(100) * 0.001 - 0.0005
result_list = []
for x0_diff in x0_diffs:
x1 = x0 + x0_diff
l_x = iterate_f(n, x0, 3.8)
l_y = iterate_f(n, x1, 3.8)
result_list.append(any(abs(l_x - l_y) > delta))
assert any(result_list)

View file

@ -0,0 +1,408 @@
#!/usr/bin/env python
# Script to send mass email
#
# Copyright (C) 2003-2017 Tiziano Zito <opossumnano@gmail.com>, Jakob Jordan <jakobjordan@posteo.de>
#
# This script is free software and comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar.
# http://www.wtfpl.net
#
# Full license text:
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004.
#
# Everyone is permitted to copy and distribute verbatim or modified
# copies of this license document, and changing it is allowed as long
# as the name is changed.
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.
import smtplib, getopt, sys, os, email, getpass
import email.header
import email.mime.text
import tempfile
from py.test import raises
PROGNAME = os.path.basename(sys.argv[0])
USAGE = """Send mass mail
Usage:
%s [...] PARAMETER_FILE < BODY
Options:
-F FROM set the From: header for all messages.
Must be ASCII. This argument is required
-S SUBJECT set the Subject: header for all messages
-B BCC set the Bcc: header for all messages.
Must be ASCII
-s SEPARATOR set field separator in parameter file,
default: ";"
-e ENCODING set PARAMETER_FILE *and* BODY character set
encoding, default: "UTF-8". Note that if you fuck
up this one, your email will be full of rubbish:
You have been warned!
-f fake run: don't really send emails, just print to
standard output what would be done. Don't be scared
if you can not read the body: it is base64 encoded
UTF8 text
-z SERVER the SMTP server to use. This argument is required
-P PORT the SMTP port to use.
-u SMTP user name. If not set, use anonymous SMTP
connection
-p SMTP password. If not set you will be prompted for one
-h show this usage message
Notes:
The message body is read from standard input or
typed in interactively (exit with ^D) and keywords are subsituted with values
read from a parameter file. The first line of the parameter file defines
the keywords. The keyword $EMAIL$ must always be present and contains a comma
separated list of email addresses.
Keep in mind shell escaping when setting headers with white spaces or special
characters.
Character set encodings are those supported by python.
Examples:
* Example of a parameter file:
$NAME$; $SURNAME$; $EMAIL$
John; Smith; j@guys.com
Anne; Joyce; a@girls.com
* Example of body:
Dear $NAME$ $SURNAME$,
I think you are a great guy/girl!
Cheers,
My self.
* Example usage:
%s -F "Great Guy <gg@guys.com>" -S "You are a great guy" -B "Not so great Guy <ngg@guys.com>" parameter-file < body
"""%(PROGNAME, PROGNAME)
def error(s):
sys.stderr.write(PROGNAME+': ')
sys.stderr.write(s+'\n')
sys.stderr.flush()
sys.exit(-1)
def parse_command_line_options(arguments):
# parse options
try:
opts, args = getopt.getopt(arguments, "hfs:F:S:B:R:e:u:p:P:z:")
except getopt.GetoptError, err:
error(str(err)+USAGE)
# set default options
options = {
'sep': u';',
'fake': False,
'from': '',
'subject': '',
'bcc': '',
'encoding': 'utf-8',
'smtpuser': None,
'smtppassword': None,
'server': None,
'port': 0,
'in_reply_to': '',
}
for option, value in opts:
if option == "-e":
options['encoding'] = value
if option == "-s":
options['sep'] = value
elif option == "-F":
options['from'] = value
elif option == "-S":
options['subject'] = value
elif option == "-B":
options['bcc'] = value
elif option == "-R":
options['in_reply_to'] = value
elif option == "-h":
error(USAGE)
elif option == "-f":
options['fake'] = True
elif option == "-u":
options['smtpuser'] = value
elif option == "-p":
options['smtppassword'] = value
elif option == "-P":
options['port'] = int(value)
elif option == "-z":
options['server'] = value
if len(args) == 0:
error('You must specify a parameter file')
if len(options['from']) == 0:
error('You must set a from address with option -F')
if options['server'] is None:
error('You must set a SMTP server with option -z')
if options['sep'] == ",":
error('Separator can not be a comma')
# get password if needed
if options['smtpuser'] is not None and options['smtppassword'] is None:
options['smtppassword'] = getpass.getpass('Enter password for %s: '%options['smtpuser'])
# set filenames of parameter and mail body
options['fn_parameters'] = args[0]
return options
def parse_parameter_file(options):
pars_fh = open(options['fn_parameters'], 'rbU')
pars = pars_fh.read()
pars_fh.close()
try:
pars = unicode(pars, encoding=options['encoding'])
except UnicodeDecodeError, e:
error('Error decoding "'+options['fn_parameters']+'": '+str(e))
try:
options['subject'] = unicode(options['subject'], encoding=options['encoding'])
except UnicodeDecodeError, e:
error('Error decoding SUBJECT: '+str(e))
try:
options['from'] = unicode(options['from'], encoding=options['encoding'])
except UnicodeDecodeError, e:
error('Error decoding FROM: '+str(e))
if options['in_reply_to'] and not options['in_reply_to'].startswith('<'):
options['in_reply_to'] = '<{}>'.format(options['in_reply_to'])
# split lines
pars = pars.splitlines()
# get keywords from first line
keywords_list = [key.strip() for key in pars[0].split(options['sep'])]
# fail immediately if no EMAIL keyword is found
if '$EMAIL$' not in keywords_list:
error('No $EMAIL$ keyword found in %s'%options['fn_parameters'])
# check that all keywords start and finish with a '$' character
for key in keywords_list:
if not key.startswith('$') or not key.endswith('$'):
error(('Keyword "%s" malformed: should be $KEYWORD$'%key).encode(options['encoding']))
# gather all values
email_count = 0
keywords = dict([(key, []) for key in keywords_list])
for count, line in enumerate(pars[1:]):
# ignore empty lines
if len(line) == 0:
continue
values = [key.strip() for key in line.split(options['sep'])]
if len(values) != len(keywords_list):
error(('Line %d in "%s" malformed: %d values found instead of'
' %d: %s'%(count+1,options['fn_parameters'],len(values),len(keywords_list),line)).encode(options['encoding']))
for i, key in enumerate(keywords_list):
keywords[key].append(values[i])
email_count += 1
return keywords, email_count
def create_email_bodies(options, keywords, email_count, body):
try:
body = unicode(body, encoding=options['encoding'])
except UnicodeDecodeError, e:
error('Error decoding email body: '+str(e))
# find keywords and substitute with values
# we need to create email_count bodies
msgs = {}
for i in range(email_count):
lbody = body
for key in keywords:
lbody = lbody.replace(key, keywords[key][i])
# Any single dollar left? That means that the body was malformed
single_dollar_exists = lbody.count('$') != 2 * lbody.count('$$')
if single_dollar_exists:
raise ValueError('Malformed email body: unclosed placeholder or non-escaped dollar sign.')
# Replace double dollars with single dollars
lbody = lbody.replace('$$', '$')
# encode body
lbody = email.mime.text.MIMEText(lbody.encode(options['encoding']), 'plain', options['encoding'])
msgs[keywords['$EMAIL$'][i]] = lbody
return msgs
def add_email_headers(options, msgs):
# msgs is now a dictionary with {emailaddr:body}
# we need to add the headers
for emailaddr in msgs:
msg = msgs[emailaddr]
msg['To'] = str(emailaddr)
msg['From'] = email.header.Header(options['from'])
if options['subject']:
msg['Subject'] = email.header.Header(options['subject'].encode(options['encoding']), options['encoding'])
if options['in_reply_to']:
msg['In-Reply-To'] = email.header.Header(options['in_reply_to'])
msgs[emailaddr] = msg
return None
def send_messages(options, msgs):
server = smtplib.SMTP(options['server'], port=options['port'])
if options['smtpuser'] is not None:
server.starttls()
server.login(options['smtpuser'], options['smtppassword'])
for emailaddr in msgs:
print 'Sending email to:', emailaddr
emails = [e.strip() for e in emailaddr.split(',')]
if len(options['bcc']) > 0:
emails.append(options['bcc'])
if options['fake']:
print msgs[emailaddr].as_string()
else:
try:
out = server.sendmail(options['from'], emails, msgs[emailaddr].as_string())
except Exception, err:
error(str(err))
if len(out) != 0:
error(str(out))
server.close()
def test_dummy():
pass
def test_parse_parameter_file():
expected_keywords = {u'$VALUE$': [u'this is a test'], u'$EMAIL$': [u'testrecv@test']}
with tempfile.NamedTemporaryFile() as f:
f.write('$EMAIL$;$VALUE$\ntestrecv@test;this is a test')
f.flush()
cmd_options = [
'-F', 'testfrom@test',
'-z', 'localhost',
f.name,
]
options = parse_command_line_options(cmd_options)
keywords, email_count = parse_parameter_file(options)
assert keywords == expected_keywords
def test_local_sending():
parameter_string = '$EMAIL$;$NAME$;$VALUE$\ntestrecv@test.org;TestName;531'
email_body = 'Dear $NAME$,\nthis is a test: $VALUE$\nBest regards'
email_to = 'testrecv@test.org'
email_from = 'testfrom@test.org'
email_subject = 'Test Subject'
email_encoding = 'utf-8'
expected_email = email.mime.text.MIMEText('Dear TestName,\nthis is a test: 531\nBest regards'.encode(email_encoding), 'plain', email_encoding)
expected_email['To'] = email_to
expected_email['From'] = email_from
expected_email['Subject'] = email.header.Header(email_subject.encode(email_encoding), email_encoding)
with tempfile.NamedTemporaryFile() as f:
f.write(parameter_string)
f.flush()
cmd_options = [
'-F', email_from,
'-S', email_subject,
'-z', 'localhost',
'-e', email_encoding,
f.name
]
options = parse_command_line_options(cmd_options)
keywords, email_count = parse_parameter_file(options)
msgs = create_email_bodies(options, keywords, email_count, email_body)
add_email_headers(options, msgs)
assert msgs['testrecv@test.org'].as_string() == expected_email.as_string()
def test_malformed_body():
parameter_string = '$EMAIL$;$NAME$;$VALUE$\ntestrecv@test.org;TestName;531'
email_body = '$NAME$VALUE$'
email_from = 'testfrom@test.org'
email_subject = 'Test Subject'
email_encoding = 'utf-8'
with tempfile.NamedTemporaryFile() as f:
f.write(parameter_string)
f.flush()
cmd_options = [
'-F', email_from,
'-S', email_subject,
'-z', 'localhost',
'-e', email_encoding,
f.name
]
options = parse_command_line_options(cmd_options)
keywords, email_count = parse_parameter_file(options)
with raises(ValueError):
msgs = create_email_bodies(options, keywords, email_count, email_body)
def test_double_dollar():
parameter_string = '$EMAIL$;$NAME$;$VALUE$\ntestrecv@test.org;TestName;531'
email_body = 'Dear $NAME$,\nyou owe us 254$$'
email_to = 'testrecv@test.org'
email_from = 'testfrom@test.org'
email_subject = 'Test Subject'
email_encoding = 'utf-8'
expected_email = email.mime.text.MIMEText('Dear TestName,\nyou owe us 254$'.encode(email_encoding), 'plain', email_encoding)
expected_email['To'] = email_to
expected_email['From'] = email_from
expected_email['Subject'] = email.header.Header(email_subject.encode(email_encoding), email_encoding)
with tempfile.NamedTemporaryFile() as f:
f.write(parameter_string)
f.flush()
cmd_options = [
'-F', email_from,
'-S', email_subject,
'-z', 'localhost',
'-e', email_encoding,
f.name
]
options = parse_command_line_options(cmd_options)
keywords, email_count = parse_parameter_file(options)
msgs = create_email_bodies(options, keywords, email_count, email_body)
assert msgs['testrecv@test.org'].get_payload(decode=email_encoding) == expected_email.get_payload(decode=email_encoding)
if __name__ == '__main__':
options = parse_command_line_options(sys.argv[1:])
keywords, email_count = parse_parameter_file(options)
msgs = create_email_bodies(options, keywords, email_count, sys.stdin.read())
add_email_headers(options, msgs)
send_messages(options, msgs)

View file

@ -0,0 +1,22 @@
from math import isclose
import numpy
def test_var_deterministic():
x = numpy.array([-2.0, 2.0])
expected = 4.0
assert isclose(numpy.var(x), expected)
def test_var_fuzzing():
rand_state = numpy.random.RandomState(8393)
N, D = 100000, 5
# Goal variances: [0.1 , 0.45, 0.8 , 1.15, 1.5]
expected = numpy.linspace(0.1, 1.5, D)
# Generate random, D-dimensional data
x = rand_state.randn(N, D) * numpy.sqrt(expected)
variance = numpy.var(x, axis=0)
numpy.testing.assert_allclose(variance, expected, rtol=1e-2)

View file

@ -0,0 +1,23 @@
import numpy as np
from numpy.testing import assert_allclose, assert_equal
def test_equality():
x = np.array([1, 1])
y = np.array([2, 2])
z = np.array([3, 3])
assert_equal(x + y, z)
def test_equality_with_nan():
x = np.array([1, np.nan])
y = np.array([2, np.nan])
z = np.array([3, np.nan])
assert_equal(x + y, z)
def test_allclose_with_nan():
x = np.array([1.1, np.nan])
y = np.array([2.2, np.nan])
z = np.array([3.3, np.nan])
assert_allclose(x + y, z)