click is a python package for creating nice commandline interfaces for your applications. I have been playing with click a bit and today pushed this simple roman numeral converter on github.
What I want to do now is to test my click application. I am reading through the documentation, but don't know how to run the tests.
Does anyone have experience with testing click applications?
Putting the code below in test_greet.py:
import click
from click.testing import CliRunner
def test_greet():
#click.command()
#click.argument('name')
def greet(name):
click.echo('Hello %s' % name)
runner = CliRunner()
result = runner.invoke(greet, ['Sam'])
assert result.output == 'Hello Sam\n'
if __name__ == '__main__':
test_greet()
If simply called with python test_greet.py the tests pass and nothing is shown. When used in a testing framework, it performs as expected. For example nosetests test_greet.py returns
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
pytest has the handlers for the asserts.
To run tests against an existing script, it must be 'imported'.
import click
from click.testing import CliRunner
from click_app import configure, cli
def test_command_configure():
runner = CliRunner()
result = runner.invoke(cli, ["configure"])
assert result.exit_code == 0
assert result.output == 'configure'
Related
I have read several posts saying that if you call your unittests with unittest.main() that they should exit with a failure code if they fail. I call my unittests with the command: python -m unittest discover -v. I am using Python 3.6.6. An example unittest could look like this:
from server import app
import unittest
class ServerTestCase(unittest.TestCase):
"""
Unittesting for the server application.
"""
def setUp(self):
"""
Create a test client
"""
self.app = app.test_client()
self.app.testing = True
def tearDown(self):
pass
def test_root_endpoint(self):
"""
Testing the root endpoint
"""
result = self.app.get('/')
self.assertEqual(result.status_code, 200)
def test_health_endpoint(self):
"""
Testing the health endpoint
"""
result = self.app.get('/health')
assert b'UP' in result.data
if __name__ == '__main__':
unittest.main()
Even if one of my tests fails I get this when checking the exit code:
$ echo $?
0
What am I doing wrong?
Did you name the unittest files something like test_*.py? Because that's what discover is looking for. Otherwise no matter your tests, the result will be:
Ran 0 tests in 0.000s
OK
(BTW you don't have to if __name__ ... unittest.main() when using -m unittest discover)
I have test cases in unittest framework. Have integrated them with teamcity.
Teamcity gives success even if my testcase fail. I Think, it is so since my unittest process exit with code 0 which is success for teamcity. I have integrated report, which show test failure. What needs to be done, so that teamcity also show failure if test fails.
code:
import unittest
class Login(unittest.TestCase):
def test_002_login_failure(self):
assert 1==2
You should prefer to use the unittest assertions so for example
self.assertEqual(1, 2)
Also you can use the teamcity-messages module to emit test messages the TeamCity will handle appropriately. Then you could change your main (if you have one) to something like the following
import teamcity
from teamcity.unittestpy import TeamcityTestRunner
if __name__ == '__main__':
if teamcity.is_running_under_teamcity():
runner = TeamcityTestRunner()
else:
runner = unittest.TextTestRunner()
unittest.main(testRunner=runner)
Ok please look at my example code
My ConnectBase class:
class ConnectBase(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['deviceName'] = '4cfe4b59'
desired_caps['platformVersion'] = '5.0'
desired_caps['appPackage'] = 'com.xyz.bookshelf'
desired_caps['appActivity'] = 'com.xyz.bookshelf.MainActivity'
desired_caps['noReset'] = False
self.driver_android = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
self.driver_android.implicitly_wait(30)
And my main file with tests:
import unittest
from connect import ConnectBase
from main_screen import MainScreenCheck
class MainTests(ConnectBase, MainScreenCheck):
with open('report.txt', 'w') as f:
f.write("----------Bookshelf----------\n")
def test_bookshelf_tutorial(self):
self.addToFile("Test Tutorial")
self.driver_android.orientation = 'LANDSCAPE'
super(MainTests, self).logout_screen_check()
def test_bookshelf_2(self):
self.addToFile("Test 2")
super(MainTests, self).login_screen_check()
def test_bookshelf_3(self):
self.addToFile("Test 3")
super(MainTests, self).loading_screen_check()
def test_bookshelf_4(self):
self.addToFile("Test 4")
super(MainTests, self).list_check()
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(MainTests)
unittest.TextTestRunner(verbosity=2).run(suite)
I run script -> it is connecting
It starts "test_bookshelf_tutorial()"
Test passed and i would like to continue with "test_bookshelf_2()" but the app is restarting... and i have to go throught tutorial screen again...
The problem is that every unittest "def test_xyz(self)" application is restarting so I can't use unittest function that shows the passed test in report becouse, each test I must go through everything that I made in tests before
I created my way to make a test report -> I'm adding each test result to txt file... but I wonder if there is a possibility to turn off this app restarting and use normal unittest reports?
Or maybe there is another great way to do reports of automation tests?
Try to make an order to your test cases, some times test depend from each other
in the first step open the application and close it only in the last step:
class MainTests(ConnectBase, TestCase):
def step1(self):
#open the application
def step2(self):
...
def steps(self):
for name in sorted(dir(self)):
if name.startswith("step"):
yield name, getattr(self, name)
def test_steps(self):
for name, step in self.steps():
try:
step()
except Exception as e:
self.fail("{} failed ({}: {})".format(step, type(e), e)
I suggest that you use a Test framework like 'TESTNG' to define test priority to manage tests order but be sure that the first test is always executed to open the application ;)
I have two test cases (two different files) that I want to run together in a Test Suite. I can get the tests to run just by running python "normally" but when I select to run a python-unit test it says 0 tests run. Right now I'm just trying to get at least one test to run correectly.
import usertest
import configtest # first test
import unittest # second test
testSuite = unittest.TestSuite()
testResult = unittest.TestResult()
confTest = configtest.ConfigTestCase()
testSuite.addTest(configtest.suite())
test = testSuite.run(testResult)
print testResult.testsRun # prints 1 if run "normally"
Here's an example of my test case set up
class ConfigTestCase(unittest.TestCase):
def setUp(self):
##set up code
def runTest(self):
#runs test
def suite():
"""
Gather all the tests from this module in a test suite.
"""
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(ConfigTestCase))
return test_suite
if __name__ == "__main__":
#So you can run tests from this module individually.
unittest.main()
What do I have to do to get this work correctly?
you want to use a testsuit. So you need not call unittest.main().
Use of testsuit should be like this:
#import usertest
#import configtest # first test
import unittest # second test
class ConfigTestCase(unittest.TestCase):
def setUp(self):
print 'stp'
##set up code
def runTest(self):
#runs test
print 'stp'
def suite():
"""
Gather all the tests from this module in a test suite.
"""
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(ConfigTestCase))
return test_suite
mySuit=suite()
runner=unittest.TextTestRunner()
runner.run(mySuit)
All of the code to create a loader and suite is unnecessary. You should write your tests so that they are runnable via test discovery using your favorite test runner. That just means naming your methods in a standard way, putting them in an importable place (or passing a folder containing them to the runner), and inheriting from unittest.TestCase. After you've done that, you can use python -m unittest discover at the simplest, or a nicer third party runner to discover and then run your tests.
If you are trying to manually collect TestCases, this is useful: unittest.loader.findTestCases():
# Given a module, M, with tests:
mySuite = unittest.loader.findTestCases(M)
runner = unittest.TextTestRunner()
runner.run(mySuit)
I am assuming you are referring to running python-unit test against the module that consolidates the two test. It will work if you create test case for that module ie. subclassing unittest.TestCase and having a simple test that starts with the word 'test'.
e.g.
class testall(unittest.TestCase):
def test_all(self):
testSuite = unittest.TestSuite()
testResult = unittest.TestResult()
confTest = configtest.ConfigTestCase()
testSuite.addTest(configtest.suite())
test = testSuite.run(testResult)
print testResult.testsRun # prints 1 if run "normally"
if __name__ == "__main__":
unittest.main()
I am a newbie in process of learning python and currently working on a automation project.
And i have N numbers of testcase which needs to be run on reading material people suggest me to use nosetest.
What is the way to run multiple testcase using nosetest?
And is the correct approach doing it:
import threading
import time
import logging
import GLOBAL
import os
from EPP import EPP
import Queue
import unittest
global EPP_Queue
from test1 import test1
from test2 import test2
logging.basicConfig(level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
class all_test(threading.Thread,unittest.TestCase):
def cleanup():
if os.path.exists("/dev/epp_dev"):
os.unlink("/dev/epp_dev")
print "starts here"
server_ip ='192.168.10.15'
EppQueue = Queue.Queue(1)
EPP = threading.Thread(name='EPP', target=EPP,
args=('192.168.10.125',54321,'/dev/ttyS17',
EppQueue,))
EPP.setDaemon(True)
EPP.start()
time.sleep(5)
suite1 = unittest.TestLoader().loadTestsFromTestCase(test1)
suite2 = unittest.TestLoader().loadTestsFromTestCase(test2)
return unittest.TestSuite([suite1, suite2])
print "final"
raw_input("keyy")
def main():
unittest.main()
if __name__ == '__main__':
main()
Read
http://ivory.idyll.org/articles/nose-intro.html.
Download the package
http://darcs.idyll.org/~t/projects/nose-demo.tar.gz
Follow the instructions provided in the first link.
nosetest, when run from command line like 'nosetest' or 'nosetest-2.6' will recursively hunt for tests in the directory you execute it in.
So if you have a directory holding N tests, just execute it in that directory. They will all be executed.