Python/Doctest - doctesting complex strings - python

I'm a student working on an assignment where I'm supposed to doctest all internal functions. My functions use complex strings and return complex strings as well, so I have no idea how to do it. For example my function "ProcessImports()" can take the string:
%#import
blahblah
%#
And return:
\begin{shadedquoteBlueBar}
\fontsize{9pt}{9pt}
\begin{Verbatim}
blahblah}
\end{Verbatim}
\end{shadedquoteBlueBar}
\noindent
How would I go around doctesting this? I've not seen any examples of using doctest that don't return classes/structs or numbers or other simple representations ("\n" doesn't seem to work, for example).
Here's the function ProcessImports():
http://pastebin.com/3JjnyKjK
Any help would be appreciated!
Edit: might wanna ignore the attempted doctest at the top. That's just me trying to mess around to find out if I can make it work and failing horribly at it.

The following example shows one successful approach; bear in mind that the doctest just needs to "look like" an interpreter session:
from textwrap import dedent
def function(s):
"""Testing doctests.
>>> print function('''%#import
... blahblah
... %#''')
<BLANKLINE>
\\begin{shadedquoteBlueBar}
\\fontsize{9pt}{9pt}
\\begin{Verbatim}
blahblah}
\\end{Verbatim}
\\end{shadedquoteBlueBar}
\\noindent
"""
s = dedent(r"""
\begin{shadedquoteBlueBar}
\fontsize{9pt}{9pt}
\begin{Verbatim}
blahblah}
\end{Verbatim}
\end{shadedquoteBlueBar}
\noindent""")
return s
Note the continuation characters ... on the input to the function within the docstring.

Related

How do I write this into a function in Python 3?

How would I write this into a function that gives the same output?
from nltk.book import text2
sorted([word.lower() for word in text2 if len(word)>4 and len(word)<12])
Functions are defined using the special keyword def followed by a function-name and parameters in parenthesis. The body of the function must be indented. Output is in general passed using the return-keyword. For this particular line of code, you can wrap it as such:
from nltk.book import text2
def funcName():
return sorted([word.lower() for word in text2 if len(word)>4 and len(word)<12])
Where funcName can be replaced with any other word, preferably something that describes what the function does more precisely.
To use the function you would add a linefuncName(). The function will then be executed, after execution, the program returns to the line where funcName was called and replaces it with the return-value of the function.
You can find more information about functions in the documentation.
I am not sure I understand you correct.
from nltk.book import text2
def my_func():
return sorted([word.lower() for word in text2 if len(word)>4 and len(word)<12])
my_func()
Welcome to StackOverflow! Unfortunately, it is not our jobs to write code FOR you, but rather help you understand where you are running into some errors.
What you want to do is learn how to lowercase strings, write conditionals (like length > 4 && < 12), and sort arrays.
Those are somewhat basic, and easy to learn functionality of python and looking up those docs can get you your answer. Once you are writing your own python code, we can better help you get your solution and point out any flaws.

Folding c.ode in python function

Let's say I have a python function like this:
class Something:
def my_function(...): <---- start fold
...
return None <---- end fold
def my_function2(...):
...
If I am on the first function line, def my_function -- and let's suppose that function is ~50 locs, how would I fold that function in vim? The first thing I thought of doing is zf/return -- but this is quite flawed, as (1) lots of functions won't have return statements; or event more common, there will be multiple return statements within a single function.
What would be the best way to do this?
(StackOverflow doesn't allow the word 'code' in a post??)
Try zf]M. ]M should act as a motion to take you to the end of the current method.
Try :set foldmethod=indent. It may work for you. VimWiki can be quite helpful though.
The problem with python is the lack of explicit block delimiters. So you may want to use some plugins like SimpylFold

Python3: Testing repeated user input

I'm a bit of a beginner in terms of unit-testing and still trying to get familiar with some of the things. This is part of my own project and I'm stuck on how to test it fully.
There was a question in this direction already, but it did only concern itself on how to repeatedly ask the user for input, not on how to unittest it.
Goal:
I have a function that asks the user for input and repeats the request if the input is invalid. My goal is to figure out how to test if the input-request is repeated if the user gives invalid input. By that I mean, I'm trying to test whether the mechanism to repeat the input-request under the defined circumstances works as intended.
The Code:
The function asks for a regular expression from the user and compiles it into an SRE_Pattern object from the re-package (python standard library). If the user provides an input and it's not a valid expression, the input-request is repeated.
import re
def request_regex_pattern(input_message):
regex_pattern = None
while True:
regex = input(input_message)
if not regex:
print("No Regex provided.")
break
try:
regex_pattern = re.compile(regex, re.IGNORECASE)
break
except re.error:
print("The input was not valid regular expression")
continue
return regex_pattern
Tests so far:
What I can test so far is whether for valid input (e.g. \d\d) I get correct output (SRE_Patternobject of that regular expression) using mocking.
import unittest as ut
from unittest import mock
import re
class TestUserInput(ut.TestCase):
def test_request_regex_pattern(self):
with mock.patch('builtins.input', return_value='\d\d'):
test_pattern = request_regex_pattern('')
test_string = '01'
self.assertIsNotNone(test_pattern.match(test_string))
I've thought about this and googled for a while now but couldn't come to a satisfying answer.
Is there a sensible way to test whether the input-request was repeated?
What are the best-practices there?
Using python's default unittest library is not mandatory for solutions. However, generally solutions using the standard libraries would be preferred as that reduces the number of requirements needed for the project I'm working on.
Thank you very much for your time !
MrBreanBremen pointed me in the right direction to linking me to his answer and kindly helped me with some of my follow-up questions regarding syntax and understanding the principle. I want to elaborate and dumb down the principles behind what he used there a bit for easier understanding.
The Principle
The way to check this is by patching a function that is called under the circumstances that you want to check. This replaces them with MagicMock-objects that know when they have been called and with which parameters !
Once the function is patched, you can then use that MagicMocks assert methods such as assert_called_with(), assert_called_once(), assert_called() and/or assert_not_called() to check whether the function that this MagicMock object replaced was called at all and with the parameters you were expecting.
Now how does this apply to this question?
First back to what is our problem. We have 3 Test-cases:
1) User provides valid regular expression that can compile into an SRE_Pattern object --> Returns an SRE_Pattern object
2) User provides no input (just hits enter) --> Returns None
3) User provide input that can't be compiled into an SRE_Pattern object (invalid input), triggering the print("The input was not valid regular expression") statement --> Never Returns anything
We only care about circumstances of 3), as case 1) and 2) have a defined output that we can check easily with "normal" unit-tests, while case 3) explicitly can't output anything, leading us to our problem.
As already hinted at in 3), under these circumstances only the print function is called. Meaning that for our test we should patch it, so that we can receive a MagicMock-object for this function and use its assert_called_with() together with the string that print-statement gets, as that string only occurs in that section of code. It is "unique" for these circumstances !
We have one more issue to solve though. Once we patch the builtins.input as before, but with something that causes our while-loop to repeat, we will still be stuck in a while-loop! The function call request_regex_pattern() will never end ! Since we can't exit the function normally, we'll have to exit by causing an Exception. Thus, we need to also patch that into one of the functions that is called when these circumstances happen. In this case, we can conveniently add this side-effect to our patch of print. We can then catch that Exception with a context-manager with self.assertRaises(Exception) to keep our test from failing.
The code:
import unittest as ut
from unittest import mock
import re
class TestUserInput(ut.TestCase):
def test_request_regex_pattern_non_regex_input(self):
with mock.patch('builtins.input', return_value='\l\d'):
with mock.patch('builtins.print', side_effect=[None, Exception('To Break the Loop!')]) as mocked_print:
with self.assertRaises(Exception):
ui.request_regex_pattern('')
mocked_print.assert_called_with('The input was not valid regular expression')
Improving Readability
This was kept with the "patch through context-manager"-syntax for consistency with the previously displayed unit-test.
As you can see, that code is not nice to read due to all the context-managers. As such, it is better to use the patch-decorator instead, as MrBreanBremen did! This will then pass the MagicMock-objects for these functions as parameters to your test, in the order that the patches are applied. Here mocked_input is the MagicMock object of the patched input() method and mocked_print is the MagicMock object of the patched print() method.
import unittest as ut
from unittest import mock
import re
class TestUserInput(ut.TestCase):
#mock.patch('builtins.input', return_value='\l\d')
#mock.patch('builtins.print', side_effect=[None, Exception('To Break the Loop!')])
def test_request_regex_pattern_non_regex_input(self, mocked_input, mocked_print):
with self.assertRaises(Exception):
request_regex_pattern('')
mocked_print.assert_called_with('The input was not valid regular expression')
A reliable way to prevent the user from entering the same input more than once would be to simply use a python built-in list. You can use a pre-determined size and just store that many elements inside it. You can append elements to the list and then if the predetermined size is exceeded pop elements from the front (oldest elements). This way you would be able to make sure that the user wouldn't be able to enter the same input as the last N (size of the list) inputs.

Run some common code before and after a block

In a current project, I found myself often writing code like so:
statement_x()
do_something()
do_other_thing()
statement_y()
# ...
statement_x()
do_third_thing()
do_fourth_thing()
statement_y()
As you can see, statement_x and statement_y often get repeated, and they are always paired, but I am unable to condense them into a single statement. What I would really like is a language construct like this:
def env wrapping:
statement_x()
run_code
statement_y()
In this case, I'm pretending env is a Python keyword indicating a special "sandwich function" that runs certain statements before and after a given block, the point of entry of the block being indicated by the second keyword run_code.
My above program can now be made more readable using this construct:
env wrapping:
do_something()
do_other_thing()
env wrapping:
do_third_thing()
do_fourth_thing()
Which I mean to have the exact same behavior.
As far as I know such a construct does not exist, and the point of my question is not to speculate on future Python features. However, surely this situation of "run some common code before and after a variable block" must occur often enough that Python has a convenient way of dealing with it! What is this way? Or is the Pythonic solution to simple give up and accept the repetition?
PS: I realize that I could write a function that takes the variable statements as an argument, but that would not be very user-friendly - I would end up writing huge lists of statements inside the parens of my function.
You can use a with statement.
Example using contextlib.contextmanager:
import contextlib
#contextlib.contextmanager
def doing_xy():
print('statement_x')
yield
print('statement_y')
Example usage:
>>> with doing_xy():
... print('do_something')
... print('do_other_thing')
...
statement_x
do_something
do_other_thing
statement_y
>>> with doing_xy():
... print('do_third_thing')
... print('do_fourth_thing')
...
statement_x
do_third_thing
do_fourth_thing
statement_y

Writing python tests like Qunitjs

I'm trying to find a similar approach to Qunit's assertions in Python. When using assertions in Qunit, the message parameter is used in a very descriptive fashion.
test( "test", function() {
ok( fn([])==None, "Function should return 0 if no users" );
ok( fn(["Test User"])==1, "Function should return 1 is users supplied" );
});
Python's unittest module on the other hand, uses the message parameter is a somewhat more negative context. These are only shown when an assertion fails.
class TestSequenceFunctions(unittest.TestCase):
def test_choice(self):
seq = range(10)
element = random.choice(seq)
self.assertTrue(element in seq, msg="Element not found in sequence")
The end result of the Qunit is that there is much clearer transcript which could be compared against a spec document.
I realise that in Python, a similar approach would be achieved by perhaps say writing
def test_choice_ensure_element_exists_in_sequence(self):
It's not the same though. The output isn't presented in a nice way, and test lifecycle then performs setup and teardown for each label you want to use, which isn't necessarily what you want.
There might be a library out there which takes this approach, so perhaps this issue is already solved. Neither the python unittest library or pytest appear to work in this fashion though.
Your problem could be simply that don't know the unittest libary well enough yet. I find being able to write
self.assertIn('s', (1,3,4))
To be very short, expressive and readable.
And if you use the correct assertion method on the testcase then you rarely need to add your own message. assertIn has a perfectly reasonable output all by itself:
AssertionError: 's' not found in (1, 3, 4)
So rather than writing heaps of comments/message code. I rely on well named assertions combined with helpful default messages. If a well named assertion and helpful error message has not already been provided then I extend the test case and add my own.
self.assert_user_is_administrator(user)
Is very readable and will have a nice message if it fails that I provided in only one location.

Categories

Resources