Selenium Python Configure Jenkins to run build. My build fails - python-2.7

I am trying to configure Jenkins to build my Selenium Webdriver Python code.
When i click Build Now it fails
The Console output shows the following:
Building in workspace C:\Program Files\Jenkins\workspace\ClearCore
[ClearCore] $ cmd /c call C:\Windows\TEMP\hudson6133135491793466847.bat
C:\Program Files\Jenkins\workspace\ClearCore>copy E:\RL Fusion\projects\Jenkins sample\ClearCore501\TestCases\*.py
The system cannot find the file specified.
C:\Program Files\Jenkins\workspace\ClearCore>python smoketests.py
python: can't open file 'smoketests.py': [Errno 2] No such file or directory
C:\Program Files\Jenkins\workspace\ClearCore>exit 2
Build step 'Execute Windows batch command' marked build as failure
Recording test results
ERROR: Publisher 'Publish JUnit test result report' failed: No test report files were found. Configuration error?
Finished: FAILURE
In PyCharm i have a smoketests.py file as follows:
import unittest
from xmlrunner import xmlrunner
from TestCases.LoginPage_TestCase import LoginPage_TestCase
from TestCases.AdministrationPage_TestCase import AdministrationPage_TestCase
from TestCases.DataConfigurationPage_TestCase import DataConfigurationPage_TestCase
login_tests = unittest.TestLoader().loadTestsFromTestCase(LoginPage_TestCase)
admin_tests = unittest.TestLoader().loadTestsFromTestCase(AdministrationPage_TestCase)
dataconf_tests = unittest.TestLoader().loadTestsFromTestCase(DataConfigurationPage_TestCase)
smoke_tests = unittest.TestSuite([login_tests, admin_tests, dataconf_tests])
xmlrunner.XMLTestRunner(verbosity=2, output='test-reports').run(smoke_tests)
I have a test_HTMLRunner.py as follows:
import unittest
import HTMLTestRunner
import os
from TestCases.LoginPage_TestCase import LoginPage_TestCase
from TestCases.AdministrationPage_TestCase import AdministrationPage_TestCase
from TestCases.DataConfigurationPage_TestCase import DataConfigurationPage_TestCase
# get the directory path to output report file
result_dir = os.getcwd()
login_tests = unittest.TestLoader().loadTestsFromTestCase(LoginPage_TestCase)
admin_tests = unittest.TestLoader().loadTestsFromTestCase(AdministrationPage_TestCase)
dataconf_tests = unittest.TestLoader().loadTestsFromTestCase(DataConfigurationPage_TestCase)
smoke_tests = unittest.TestSuite([login_tests, admin_tests, dataconf_tests])
# open the report file
outfile = open(result_dir + "\TestReport.html", "w")
# configure HTMLTestRunner options
runner = HTMLTestRunner.HTMLTestRunner(stream=outfile,
title='Test Report',
description='LADEMO create a basic project test')
# run the suite using HTMLTestRunner
runner.run(smoke_tests)
I have a suite.py as follows:
import sys
import unittest
import HTMLTestRunner
import os
import unittest
import AdministrationPage_TestCase
import LoginPage_TestCase
import DataConfigurationPage_TestCase
class Test_Suite(unittest.TestCase):
def test_main(self):
# suite of TestCases
self.suite = unittest.TestSuite()
self.suite.addTests([
unittest.defaultTestLoader.loadTestsFromTestCase(LoginPage_TestCase.LoginPage_TestCase),
unittest.defaultTestLoader.loadTestsFromTestCase(AdministrationPage_TestCase.AdministrationPage_TestCase),
unittest.defaultTestLoader.loadTestsFromTestCase(DataConfigurationPage_TestCase.DataConfigurationPage_TestCase),
])
runner = unittest.TextTestRunner()
runner.run (self.suite)
import unittest
if __name__ == "__main__":
unittest.main()
In Jenkins I have configured the following:
From the section Build, Execute Windows Batch Command
copy E:\RL Fusion\projects\Jenkins sample\ClearCore501\TestCases\*.py
python smoketests.py
From the section Post-Build Actions, Publish JUnit test result report
test_reports/*..xml
Below test_reports/*..xml it shows:
‘test_reports/*..xml’ doesn’t match anything: even ‘test_reports’ doesn’t exist
How do i get this to work please? What am i doing wrong?
Is there any sample demo I could follow and then I can get my setup to work?
Thanks,
Riaz

The problem looks to be in the copy step of you batch file. Notice how it says it cant find the file. Surround the source and destination paths with double quotes so that windows knows your path has spaces in it.
It also appears the copy operation doesn't have a destination specified. You should may want to specify that too. Although apparently that isn't a requirement, as I just found out :).
Once the copy operation succeeds, check the workspace directory to see if the file(s) you expect are present.
Alternatively, you can tell the Jenkins job to use a custom workspace, the directory where your tests live. With this configuration you don't even have to worry about copying files.
Here's how:
In the job config in Jenkins, open the Advanced Project Options and select use custom workspace and set the directory to E:\RL Fusion\projects\Jenkins sample\ClearCore501\TestCases\.
Then the build command can just be python smoketests.py.

Related

How do I use "discover" to run tests in my "tests" directory?

Using DJango/Python 3.7. I read here -- How do I run all Python unit tests in a directory? that I could use a "discover" command to find tests in a specified directory. I want to have a "tests" folder, so I cretaed one and then ran
(venv) localhost:myproject davea$ python -m unittest discover tests
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/__main__.py", line 18, in <module>
main(module=None)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 100, in __init__
self.parseArgs(argv)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 124, in parseArgs
self._do_discovery(argv[2:])
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 244, in _do_discovery
self.createTests(from_discovery=True, Loader=Loader)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 154, in createTests
self.test = loader.discover(self.start, self.pattern, self.top)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 344, in discover
raise ImportError('Start directory is not importable: %r' % start_dir)
ImportError: Start directory is not importable: 'tests'
This is odd to me because I have an (empty) init file ...
(venv) localhost:myproject davea$ ls web/tests/
__init__.py model_tests.py
What else do I need to do to get my test directory recognized?
Edit: Below are the contents of model_tests.py ...
from django.conf import settings
from django.test import TestCase
from django.core import management
def setup():
print("setup")
management.call_command('loaddata', 'test_data.yaml', verbosity=0)
def teardown():
management.call_command('flush', verbosity=0, interactive=False)
class ModelTest(TestCase):
# Verify we can correctly calculate the amount of taxes when we are working
# with a state whose tax rates are defined in our test data
def test_calculate_tax_rate_for_defined_state(self):
state = "MN"
income = 30000
taxes = IndividualTaxBracket.objects.get_taxes_owed(state, income)
print(taxes)
self.assertTrue(taxes > 0, "Failed to calucate taxes owed properly.")
I think you are having some confusion about discover command. According to docs.
Unittest supports simple test discovery. In order to be compatible
with test discovery, all of the test files must be modules or packages
(including namespace packages) importable from the top-level directory
of the project (this means that their filenames must be valid
identifiers).
It means all the test files must be importable from the directory from which you are running the command (directory that holds your web directory). It make this sure, all test files must be in valid python packages (directories containing __init__.py).
Secondly you are running the command python -m unittest discover tests which is wrong. You don't have to add tests at the end. unittests with discover command support 4 options. You can read more about it here.
I have following directory structure.
web
├── __init__.py
└── tests
├── __init__.py
└── test_models.py
And I am running following command.
python3 -m unittest discover
With following results.
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
First things first: Having an __init__.py is not unusual, because the __init__.py tells python that the directory is a module; Its usual to have an empty __init__.py file. I had the same error, and fixed it by renaming my directory ..
Should a file named tests.py exist as a sibling of tests module, that would probably cause the mentioned ImportError, and removing test.py should fix it.
If still unit tests are not discovered, a couple of question are in order:
1) does the test module contain at least a class derived from django.test.TestCase ?
2) and in that case, does that class contain at least one method whose name starts with "test_"
Please note that the name of any file containing a unit test should start with "test".
So model_test.py will not work; is is generally used to setup some fake Models, but unit tests should reside elsewhere.
You can discover and run tests with this management command:
python manage.py test
or
python manage.py test appname
Is there any particular reason for using python -m unittest discover instead ? I think that could work either, but then you'll have to manually bootstrap the django environment
For completion ...
You already know that form here:
The names of your tests and files have to match a specific pattern in order to be discoverable by discover().
But then you got this error:
"django.core.exceptions.ImproperlyConfigured: Requested settings, but settings are not configured"
That means Django wasn't able to find its settings while running your tests. You can tell where to find settings using an environment variable:
DJANGO_SETTINGS_MODULE='myproyect.settings' python3 -m unittest discover
Reference: https://docs.djangoproject.com/en/2.2/topics/settings/#designating-the-settings
On the other hand ...
You should be running your Django tests with
./manage.py tests
this will search tests automatically using the same mechanism than discover(), and since you would be running a Django command, you will have some benefits against running the Django tests directly.
#Nafees Anwar asked: How does setting environment variable configure settings?
At the very beginning of the model_tests.py file there is the line from django.conf import settings, while creating the settings LazyObject instance, Django will search for that environment variable. Read the code for more detail.
I'll post here a snippet from that code for illustration.
# django.conf module.
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
class LazySettings(LazyObject):
"""
A lazy proxy for either global Django settings or a custom settings object.
The user can manually configure settings prior to using them. Otherwise,
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
"""
def _setup(self, name=None):
"""
Load the settings module pointed to by the environment variable. This
is used the first time we need any settings at all, if the user has not
previously configured the settings manually.
"""
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
if not settings_module:
desc = ("setting %s" % name) if name else "settings"
raise ImproperlyConfigured(
"Requested %s, but settings are not configured. "
"You must either define the environment variable %s "
"or call settings.configure() before accessing settings."
% (desc, ENVIRONMENT_VARIABLE))
self._wrapped = Settings(settings_module)
So if you do:
from django.conf import settings
having that environment variable settled, the statement
settings.configure()
will fail with RuntimeError('Settings already configured.')

Imported library 'owaspapi' contains no keywords. (if it's installed using pip)

I have made a library for Robot Framework (myapi.py). If I place it in the same directory with my robot test I can import the library like this:
Library myapi.py
It works just fine.
However, I made the library pip installable so that others may take it into use in other projects easily. The library installs just fine with pip. I also changed the robot test to import the library like this:
Library myapi
When I run the robot test I get warning:
[ WARN ] Imported library 'myapi' contains no keywords.
Here's the (pip installable) library file structure:
setup.py
myapi
\__init__.py
\myapi.py
\version.py
The setup.py content is:
from setuptools import setup, find_packages
exec(open('myapi/version.py').read())
setup(
name='myapi',
version=__version__,
packages=['myapi'],
install_requires=['requests']
)
The init.py content is:
from .version import __version__
The version.py content is:
__version__ = '1.1.0'
The myapi.py content is (included only the first function I have):
import requests
import time
from time import strftime
import urllib2
__all__ = ['create_new_MY_session']
def create_new_MY_session():
session_name = strftime('my_session_%S_%H_%M_%d_%m_%Y')
r = requests.get("http://localhost:8080/JSON/core/action/newSession/?zapapiformat=JSON&name=" + session_name + "/'")
print ("Creating new session: " + session_name + ". Status code...")
print (r.status_code)
assert (r.status_code) == 200
And finally the beginning of the robot test (login.robot):
*** Settings ***
Suite Setup Open Firefox With Proxy
Suite Teardown Close Browser
Library mypapi
Library OperatingSystem
Library Selenium2Library
Resource ws_keywords/product/webui.robot
*** Test Cases ***
MY Start New MY Session
Create New MY Session
I wonder if the library works just fine when located right next to the robot test, what am I missing if I make it pip installable...? Why does it complain that there are no keywords?
In your myapi.py file you missing the class reference. When the file is placed inside your Robot Framework project this wasn't an issue, but when creating a pip installable module, this is required. A basic Python Library code example is this:
myapi.py
class myapi(object):
ROBOT_LIBRARY_VERSION = 1.0
def __init__(self):
pass
def keyword(self):
pass

PyCharm can't find 'SPARK_HOME' when imported from a different file

I've two files.
test.py
from pyspark import SparkContext
from pyspark import SparkConf
from pyspark import SQLContext
class Connection():
conf = SparkConf()
conf.setMaster("local")
conf.setAppName("Remote_Spark_Program - Leschi Plans")
conf.set('spark.executor.instances', 1)
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)
print ('all done.')
con = Connection()
test_test.py
from test import Connection
sparkConnect = Connection()
when I run test.py the connection is made successfully but with test_test.py it gives
raise KeyError(key)
KeyError: 'SPARK_HOME'
KEY_ERROR arises if the SPARK_HOME is not found or invalid. So it's better to add it to your bashrc and check and reload in your code. So add this at the top of your test.py
import os
import sys
import pyspark
from pyspark import SparkContext, SparkConf, SQLContext
# Create a variable for our root path
SPARK_HOME = os.environ.get('SPARK_HOME',None)
# Add the PySpark/py4j to the Python Path
sys.path.insert(0, os.path.join(SPARK_HOME, "python", "lib"))
sys.path.insert(0, os.path.join(SPARK_HOME, "python"))
pyspark_submit_args = os.environ.get("PYSPARK_SUBMIT_ARGS", "")
if not "pyspark-shell" in pyspark_submit_args: pyspark_submit_args += " pyspark-shell"
os.environ["PYSPARK_SUBMIT_ARGS"] = pyspark_submit_args
Also add this at the end of your ~/.bashrc file
COMMAND: vim ~/.bashrc if you are using any Linux based OS
# needed for Apache Spark
export SPARK_HOME="/opt/spark"
export IPYTHON="1"
export PYSPARK_PYTHON="/usr/bin/python3"
export PYSPARK_DRIVER_PYTHON="ipython3"
export PYSPARK_DRIVER_PYTHON_OPTS="notebook"
export PYTHONPATH="$SPARK_HOME/python/:$PYTHONPATH"
export PYTHONPATH="$SPARK_HOME/python/lib/py4j-0.9-src.zip:$PYTHONPATH"
export PYSPARK_SUBMIT_ARGS="--master local[2] pyspark-shell"
export CLASSPATH="$CLASSPATH:/opt/spark/lib/spark-assembly-1.6.1-hadoop2.6.0.jar
Note:
In the above bashrc code, I have given my SPARK_HOME value as /opt/spark you can give the location where you keep your spark folder(the downloaded one from the website).
Also I'm using python3 you can change it to python in the bashrc if you are using python 2.+ versions
I was using Ipython, for easy testing during runtime, like load the data once and test your code many times. If you are using plain old text editor, let me know I will update the bashrc accordingly.

Add method imports to shell_plus

In shell_plus, is there a way to automatically import selected helper methods, like the models are?
I often open the shell to type:
proj = Project.objects.get(project_id="asdf")
I want to replace that with:
proj = getproj("asdf")
Found it in the docs. Quoted from there:
Additional Imports
In addition to importing the models you can specify other items to
import by default. These are specified in SHELL_PLUS_PRE_IMPORTS and
SHELL_PLUS_POST_IMPORTS. The former is imported before any other
imports (such as the default models import) and the latter is imported
after any other imports. Both have similar syntax. So in your
settings.py file:
SHELL_PLUS_PRE_IMPORTS = (
('module.submodule1', ('class1', 'function2')),
('module.submodule2', 'function3'),
('module.submodule3', '*'),
'module.submodule4'
)
The above example would directly translate to the following python
code which would be executed before the automatic imports:
from module.submodule1 import class1, function2
from module.submodule2 import function3
from module.submodule3 import *
import module.submodule4
These symbols will be available as soon as the shell starts.
ok, two ways:
1) using PYTHONSTARTUP variable (see this Docs)
#in some file. (here, I'll call it "~/path/to/foo.py"
def getproj(p_od):
#I'm importing here because this script run in any python shell session
from some_app.models import Project
return Project.objects.get(project_id="asdf")
#in your .bashrc
export PYTHONSTARTUP="~/path/to/foo.py"
2) using ipython startup (my favourite) (See this Docs,this issue and this Docs ):
$ pip install ipython
$ ipython profile create
# put the foo.py script in your profile_default/startup directory.
# django run ipython if it's installed.
$ django-admin.py shell_plus

How to test custom django-admin commands

I created custom django-admin commands
But, I don't know how to test it in standard django tests
If you're using some coverage tool it would be good to call it from the code with:
from django.core.management import call_command
from django.test import TestCase
class CommandsTestCase(TestCase):
def test_mycommand(self):
" Test my custom command."
args = []
opts = {}
call_command('mycommand', *args, **opts)
# Some Asserts.
From the official documentation
Management commands can be tested with the call_command() function. The output can be redirected into a StringIO instance
You should make your actual command script the minimum possible, so that it just calls a function elsewhere. The function can then be tested via unit tests or doctests as normal.
you can see in github.com example
see here
def test_command_style(self):
out = StringIO()
management.call_command('dance', style='Jive', stdout=out)
self.assertEquals(out.getvalue(),
"I don't feel like dancing Jive.")
To add to what has already been posted here. If your django-admin command passes a file as parameter, you could do something like this:
from django.test import TestCase
from django.core.management import call_command
from io import StringIO
import os
class CommandTestCase(TestCase):
def test_command_import(self):
out = StringIO()
call_command(
'my_command', os.path.join('path/to/file', 'my_file.txt'),
stdout=out
)
self.assertIn(
'Expected Value',
out.getvalue()
)
This works when your django-command is used in a manner like this:
$ python manage.py my_command my_file.txt
A simple alternative to parsing stdout is to make your management command exit with an error code if it doesn't run successfully, for example using sys.exit(1).
You can catch this in a test with:
with self.assertRaises(SystemExit):
call_command('mycommand')
I agree with Daniel that the actual command script should do the minimum possible but you can also test it directly in a Django unit test using os.popen4.
From within your unit test you can have a command like
fin, fout = os.popen4('python manage.py yourcommand')
result = fout.read()
You can then analyze the contents of result to test whether your Django command was successful.