24 Jul 2014
·
If you mock some thing, it can’t be runnable. Don’t forget it just mock object.
Mock Method that can be runnable
# side_effect will make mock method can be runable
# this can be use to reutrn_value in different arguments
>>> mock_method = mock . Mock ()
>>> mock_method . side_effect = lambda x : x + 1
>>> mock_method ( 1 )
2
>>> mock_method ( 2 )
3
Patch Module Attribute
# Using PropertyMock with return_value argument
>>> with mock . patch ( 'package.module.attribute' ,
new_callable = mock . PropertyMock ( return_value = 3 ))
as mock_attribute :
>>> print ( mock_attribte )
>>> print ( package . module . attribute )
3
3
my_mock.mock_calls
Reference:
The Mock Class
enhancing-python-unit-tests-with-more-decorators
python-decorators-with-parameters
20 Jul 2014
·
Python API and shell utilities to monitor file system events.
Watching python file changes
#!/usr/bin/env python
import os
import sys
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
def when_file_changed(filename):
"""
Unittest Monitoring with coverage filtering
file - ./<projectname>/<package>/<file>.py
ex. ./meow_meow/core/api.py
testfile - ./tests/unit/<package>/test_<file>.py
ex. ./tests/unit/core/test_api.py
"""
def projectname():
"""
Projectname from name of current directory ('.')
if there are dash '-' in its name replace to underscore '_'
"""
return os.path.abspath(".").rsplit("/", 1)[1].replace("-", "_")
def package(filename):
basename = os.path.basename(filename)
if not basename.startswith("test_"):
package = filename.replace("./", "").replace(".py", "")
else:
package = filename.replace("./tests/unit", "").replace(".py", "")
package = projectname() + package.replace("/test_", "/")
package = package.replace("/", ".")
return package
def test_file(filename):
basename = os.path.basename(filename)
if not basename.startswith("test_"):
filename = filename.replace(projectname(), "tests/unit")
filename = filename.replace(basename, "test_" + basename)
return filename
cls()
print(os.path.abspath(filename))
args = {"package": package(filename), "testfile": test_file(filename)}
cmd = "nosetests --with-coverage --cover-erase --cover-package={package}" \
" -v {testfile}".format(**args)
os.system(cmd)
def cls():
os.system('cls' if os.name == 'nt' else 'clear')
class ModifiedHandler(PatternMatchingEventHandler):
patterns = ["*.py"] # Monitor only matched patterns
def on_created(self, event):
"""" For Vim :w - not modify that deleted and created file instead. """
when_file_changed(event.src_path)
def on_modified(self, event):
""" For other text-editor ex.sublime """
when_file_changed(event.src_path)
if __name__ == '__main__':
args = sys.argv[1:]
event_handler = ModifiedHandler()
observer = Observer()
observer.schedule(event_handler,
path=args[1] if args else '.', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Watchdog over Docker (VM) via polling - Ref
from watchdog.observers.polling import PollingObserver as Observer
Observer () #polling every 1 second
References:
Event Handler Classes
Watching a directory for file changes
Continuous integration in python using watchdog
19 Jul 2014
·
Continuous Integrations doesn’t get rid of bugs, but it does make them dramatically easier to find and remove. - Continuous Integration by Martin Fowler
Own Sever Services
Online Services
11 Jul 2014
·
There are difference between ‘building it right’ and ‘building the right thing’. -Python Testing Cookbook by Greg L. Turnquist
Good Test Habits
A few test is better than nothing
Coverage isn’t everything
make working software not a 100% coverage
Capturing a bug in an automated test
Write Tests for the bug
Add it to your test suite
Fix the bug
Veriry test suite passed
Testing Concept
AAA - Arrange Act Assert
BDD - Give When Then
Tips:
Run All unittest in module:
python -m unittest discover <test_module>
Run nosetests with python3.
Install nose into python3 package with pip3 then you can run nosetests with python3 via nosetests-3.x ex. nosetests-3.4 if your python3 is version 3.4
# ubuntu install python3-pip first
# $ sudo apt-get install python3-ip
$ pip3 install nose
$ nosetests-3.x
Problems using nose in a virtualenv
you can’t run nose in system-packages to using packages in virtualenv (sandbox)
Run PDB with nosetest:
from nose.tools import set_trace ; set_trace ()
You should make unittest run faster with mocking better than using multi processes.
There are many problem with nose plugin ex. rednose, coverage, xunit.
In worst case more processeses can make your tests slower depends on your tests.
$ nosetests --processes = NUMBER_OF_PROCESSORS --process-timeout <sec>
Plugin Problem :
Rednose - disable rednose by remove –rednose option and NOSE_REDNOSE in enviorment variable
coverage - fix by nose-cov
xunit - fix by nose_xunitmp
Test Coverage
Stmts - statements
Miss - statements that not executed
Cover - (Stmts - Miss)/Stmts * 100
Mock
Behavior Driven Development
Acceptance testing is block box testing
Customers are usually more interested in what the software does, not how it does it.
Robot Framework uses keywords to define tests, test steps, variables, and other testing components and need to maps Robot Framework keywords to our Python code
Robot Framework uses data-driven test suite
Jekin(Java) - Continuous Integration
nosetests –with-xunit
tests upon commit(trigger),when scheduled
pip install nose rednose coverage
echo "export NOSE_REDNOSE=1" >> .zshrc #enable rednose
Tox - multiple environments testing
Testing Python
Python Testing Start Here
Testing in Python: using nose & mocks
Mock - Mocking and Testing Library
An Introduction to Mocking in Python
INTRODUCING BDD
Mock Like a Boss
Beginning Test-Driven Development in Python
Behavior-Driven Development in Python
Testing with mock
Software Testing Course
Patching Mocks in Python
Python Nose: Speed up the runner
Beginning Test-Driven Development in Python
python-test-double
Mocking in Python - How to Bypass Expensive and External Code Within Your Tests