Mistral Horizon plugin.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

run_tests.sh 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. #!/bin/bash
  2. set -o errexit
  3. function usage {
  4. echo "Usage: $0 [OPTION]..."
  5. echo "Run Mistral Dashboard's test suite(s)"
  6. echo ""
  7. echo " -V, --virtual-env Always use virtualenv. Install automatically"
  8. echo " if not present"
  9. echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local"
  10. echo " environment"
  11. echo " -c, --coverage Generate reports using Coverage"
  12. echo " -f, --force Force a clean re-build of the virtual"
  13. echo " environment. Useful when dependencies have"
  14. echo " been added."
  15. echo " -m, --manage Run a Django management command."
  16. echo " --pseudo Pseudo translate a language."
  17. echo " -p, --pep8 Just run pep8"
  18. echo " -8, --pep8-changed [<basecommit>]"
  19. echo " Just run PEP8 and HACKING compliance check"
  20. echo " on files changed since HEAD~1 (or <basecommit>)"
  21. echo " -P, --no-pep8 Don't run pep8 by default"
  22. echo " -t, --tabs Check for tab characters in files."
  23. echo " -y, --pylint Just run pylint"
  24. echo " -q, --quiet Run non-interactively. (Relatively) quiet."
  25. echo " Implies -V if -N is not set."
  26. echo " --only-selenium Run only the Selenium unit tests"
  27. echo " --with-selenium Run unit tests including Selenium tests"
  28. echo " --selenium-headless Run Selenium tests headless"
  29. echo " --runserver Run the Django development server for"
  30. echo " mistraldashboard in the virtual"
  31. echo " environment."
  32. echo " --docs Just build the documentation"
  33. echo " --backup-environment Make a backup of the environment on exit"
  34. echo " --restore-environment Restore the environment before running"
  35. echo " --destroy-environment Destroy the environment and exit"
  36. echo " -h, --help Print this usage message"
  37. echo ""
  38. echo "Note: with no options specified, the script will try to run the tests in"
  39. echo " a virtual environment, If no virtualenv is found, the script will ask"
  40. echo " if you would like to create one. If you prefer to run tests NOT in a"
  41. echo " virtual environment, simply pass the -N option."
  42. exit
  43. }
  44. # DEFAULTS FOR RUN_TESTS.SH
  45. #
  46. root=`pwd -P`
  47. venv=$root/.venv
  48. venv_env_version=$venv/environments
  49. with_venv=tools/with_venv.sh
  50. included_dirs="mistraldashboard"
  51. always_venv=0
  52. backup_env=0
  53. command_wrapper=""
  54. destroy=0
  55. force=0
  56. just_pep8=0
  57. just_pep8_changed=0
  58. no_pep8=0
  59. just_pylint=0
  60. just_docs=0
  61. just_tabs=0
  62. never_venv=0
  63. quiet=0
  64. restore_env=0
  65. runserver=0
  66. only_selenium=0
  67. with_selenium=0
  68. selenium_headless=0
  69. testopts=""
  70. testargs=""
  71. with_coverage=0
  72. check_only=0
  73. pseudo=0
  74. manage=0
  75. # Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default"
  76. [ "$JOB_NAME" ] || JOB_NAME="default"
  77. function process_option {
  78. # If running manage command, treat the rest of options as arguments.
  79. if [ $manage -eq 1 ]; then
  80. testargs="$testargs $1"
  81. return 0
  82. fi
  83. case "$1" in
  84. -h|--help) usage;;
  85. -V|--virtual-env) always_venv=1; never_venv=0;;
  86. -N|--no-virtual-env) always_venv=0; never_venv=1;;
  87. -p|--pep8) just_pep8=1;;
  88. -8|--pep8-changed) just_pep8_changed=1;;
  89. -P|--no-pep8) no_pep8=1;;
  90. -y|--pylint) just_pylint=1;;
  91. -f|--force) force=1;;
  92. -t|--tabs) just_tabs=1;;
  93. -q|--quiet) quiet=1;;
  94. -c|--coverage) with_coverage=1;;
  95. -m|--manage) manage=1;;
  96. --pseudo) pseudo=1;;
  97. --only-selenium) only_selenium=1;;
  98. --with-selenium) with_selenium=1;;
  99. --selenium-headless) selenium_headless=1;;
  100. --docs) just_docs=1;;
  101. --runserver) runserver=1;;
  102. --backup-environment) backup_env=1;;
  103. --restore-environment) restore_env=1;;
  104. --destroy-environment) destroy=1;;
  105. -*) testopts="$testopts $1";;
  106. *) testargs="$testargs $1"
  107. esac
  108. }
  109. function run_management_command {
  110. ${command_wrapper} python $root/manage.py $testopts $testargs
  111. }
  112. function run_server {
  113. echo "Starting Django development server..."
  114. ${command_wrapper} python $root/manage.py runserver $testopts $testargs
  115. echo "Server stopped."
  116. }
  117. function run_pylint {
  118. echo "Running pylint ..."
  119. PYTHONPATH=$root ${command_wrapper} pylint --rcfile=.pylintrc -f parseable $included_dirs > pylint.txt || true
  120. CODE=$?
  121. grep Global -A2 pylint.txt
  122. if [ $CODE -lt 32 ]; then
  123. echo "Completed successfully."
  124. exit 0
  125. else
  126. echo "Completed with problems."
  127. exit $CODE
  128. fi
  129. }
  130. function warn_on_flake8_without_venv {
  131. set +o errexit
  132. ${command_wrapper} python -c "import hacking" 2>/dev/null
  133. no_hacking=$?
  134. set -o errexit
  135. if [ $never_venv -eq 1 -a $no_hacking -eq 1 ]; then
  136. echo "**WARNING**:" >&2
  137. echo "OpenStack hacking is not installed on your host. Its detection will be missed." >&2
  138. echo "Please install or use virtual env if you need OpenStack hacking detection." >&2
  139. fi
  140. }
  141. function run_pep8 {
  142. echo "Running flake8 ..."
  143. warn_on_flake8_without_venv
  144. DJANGO_SETTINGS_MODULE=mistraldashboard.test.settings ${command_wrapper} flake8 $included_dirs
  145. }
  146. function run_pep8_changed {
  147. local base_commit=${testargs:-HEAD~1}
  148. files=$(git diff --name-only $base_commit | tr '\n' ' ')
  149. echo "Running flake8 on ${files}"
  150. warn_on_flake8_without_venv
  151. diff -u --from-file /dev/null ${files} | DJANGO_SETTINGS_MODULE=mistraldashboard.test.settings ${command_wrapper} flake8 --diff
  152. exit
  153. }
  154. function run_sphinx {
  155. echo "Building sphinx..."
  156. export DJANGO_SETTINGS_MODULE=mistraldashboard.test.settings
  157. ${command_wrapper} sphinx-build -b html doc/source doc/build/html
  158. echo "Build complete."
  159. }
  160. function tab_check {
  161. TAB_VIOLATIONS=`find $included_dirs -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l`
  162. if [ $TAB_VIOLATIONS -gt 0 ]; then
  163. echo "TABS! $TAB_VIOLATIONS of them! Oh no!"
  164. HORIZON_FILES=`find $included_dirs -type f -regex ".*\.\(css\|js\|py|\html\)"`
  165. for TABBED_FILE in $HORIZON_FILES
  166. do
  167. TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l`
  168. if [ $TAB_COUNT -gt 0 ]; then
  169. echo "$TABBED_FILE: $TAB_COUNT"
  170. fi
  171. done
  172. fi
  173. return $TAB_VIOLATIONS;
  174. }
  175. function destroy_venv {
  176. echo "Cleaning environment..."
  177. echo "Removing virtualenv..."
  178. rm -rf $venv
  179. echo "Virtualenv removed."
  180. }
  181. function environment_check {
  182. echo "Checking environment."
  183. if [ -f $venv_env_version ]; then
  184. set +o errexit
  185. cat requirements.txt test-requirements.txt | cmp $venv_env_version - > /dev/null
  186. local env_check_result=$?
  187. set -o errexit
  188. if [ $env_check_result -eq 0 ]; then
  189. # If the environment exists and is up-to-date then set our variables
  190. command_wrapper="${root}/${with_venv}"
  191. echo "Environment is up to date."
  192. return 0
  193. fi
  194. fi
  195. if [ $always_venv -eq 1 ]; then
  196. install_venv
  197. else
  198. if [ ! -e ${venv} ]; then
  199. echo -e "Environment not found. Install? (Y/n) \c"
  200. else
  201. echo -e "Your environment appears to be out of date. Update? (Y/n) \c"
  202. fi
  203. read update_env
  204. if [ "x$update_env" = "xY" -o "x$update_env" = "x" -o "x$update_env" = "xy" ]; then
  205. install_venv
  206. else
  207. # Set our command wrapper anyway.
  208. command_wrapper="${root}/${with_venv}"
  209. fi
  210. fi
  211. }
  212. function sanity_check {
  213. # Anything that should be determined prior to running the tests, server, etc.
  214. # Don't sanity-check anything environment-related in -N flag is set
  215. if [ $never_venv -eq 0 ]; then
  216. if [ ! -e ${venv} ]; then
  217. echo "Virtualenv not found at $venv. Did install_venv.py succeed?"
  218. exit 1
  219. fi
  220. fi
  221. # Remove .pyc files. This is sanity checking because they can linger
  222. # after old files are deleted.
  223. find . -name "*.pyc" -exec rm -rf {} \;
  224. }
  225. function backup_environment {
  226. if [ $backup_env -eq 1 ]; then
  227. echo "Backing up environment \"$JOB_NAME\"..."
  228. if [ ! -e ${venv} ]; then
  229. echo "Environment not installed. Cannot back up."
  230. return 0
  231. fi
  232. if [ -d /tmp/.mistral_dashboard_environment/$JOB_NAME ]; then
  233. mv /tmp/.mistral_dashboard_environment/$JOB_NAME /tmp/.mistral_dashboard_environment/$JOB_NAME.old
  234. rm -rf /tmp/.mistral_dashboard_environment/$JOB_NAME
  235. fi
  236. mkdir -p /tmp/.mistral_dashboard_environment/$JOB_NAME
  237. cp -r $venv /tmp/.mistral_dashboard_environment/$JOB_NAME/
  238. cp .environment_version /tmp/.mistral_dashboard_environment/$JOB_NAME/
  239. # Remove the backup now that we've completed successfully
  240. rm -rf /tmp/.mistral_dashboard_environment/$JOB_NAME.old
  241. echo "Backup completed"
  242. fi
  243. }
  244. function restore_environment {
  245. if [ $restore_env -eq 1 ]; then
  246. echo "Restoring environment from backup..."
  247. if [ ! -d /tmp/.mistral_dashboard_environment/$JOB_NAME ]; then
  248. echo "No backup to restore from."
  249. return 0
  250. fi
  251. cp -r /tmp/.mistral_dashboard_environment/$JOB_NAME/.venv ./ || true
  252. echo "Environment restored successfully."
  253. fi
  254. }
  255. function install_venv {
  256. # Install with install_venv.py
  257. export PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE-/tmp/.pip_download_cache}
  258. export PIP_USE_MIRRORS=true
  259. if [ $quiet -eq 1 ]; then
  260. export PIP_NO_INPUT=true
  261. fi
  262. echo "Fetching new src packages..."
  263. rm -rf $venv/src
  264. python tools/install_venv.py
  265. command_wrapper="$root/${with_venv}"
  266. # Make sure it worked and record the environment version
  267. sanity_check
  268. chmod -R 754 $venv
  269. cat requirements.txt test-requirements.txt > $venv_env_version
  270. }
  271. function run_tests {
  272. sanity_check
  273. if [ $with_selenium -eq 1 ]; then
  274. export WITH_SELENIUM=1
  275. elif [ $only_selenium -eq 1 ]; then
  276. export WITH_SELENIUM=1
  277. export SKIP_UNITTESTS=1
  278. fi
  279. if [ $selenium_headless -eq 1 ]; then
  280. export SELENIUM_HEADLESS=1
  281. fi
  282. if [ -z "$testargs" ]; then
  283. run_tests_all
  284. else
  285. run_tests_subset
  286. fi
  287. }
  288. function run_tests_subset {
  289. project=`echo $testargs | awk -F. '{print $1}'`
  290. ${command_wrapper} python $root/manage.py test --settings=$project.test.settings $testopts $testargs
  291. }
  292. function run_tests_all {
  293. echo "Running Mistral-Dashboard application tests"
  294. export NOSE_XUNIT_FILE=mistraldashboard/nosetests.xml
  295. if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then
  296. export NOSE_HTML_OUT_FILE='mistral_dashboard_nose_results.html'
  297. fi
  298. if [ $with_coverage -eq 1 ]; then
  299. ${command_wrapper} python -m coverage.__main__ erase
  300. coverage_run="python -m coverage.__main__ run -p"
  301. fi
  302. ${command_wrapper} ${coverage_run} $root/manage.py test mistraldashboard --settings=mistraldashboard.test.settings $testopts
  303. # get results of the Horizon tests
  304. TUSKAR_UI_RESULT=$?
  305. if [ $with_coverage -eq 1 ]; then
  306. echo "Generating coverage reports"
  307. ${command_wrapper} python -m coverage.__main__ combine
  308. ${command_wrapper} python -m coverage.__main__ xml -i --include="mistraldashboard/*" --omit='/usr*,setup.py,*egg*,.venv/*'
  309. ${command_wrapper} python -m coverage.__main__ html -i --include="mistraldashboard/*" --omit='/usr*,setup.py,*egg*,.venv/*' -d reports
  310. fi
  311. # Remove the leftover coverage files from the -p flag earlier.
  312. rm -f .coverage.*
  313. PEP8_RESULT=0
  314. if [ $only_selenium -eq 0 ]; then
  315. run_pep8
  316. PEP8_RESULT=$?
  317. fi
  318. TEST_RESULT=$(($TUSKAR_UI_RESULT || $PEP8_RESULT))
  319. if [ $TEST_RESULT -eq 0 ]; then
  320. echo "Tests completed successfully."
  321. else
  322. echo "Tests failed."
  323. fi
  324. exit $TEST_RESULT
  325. }
  326. # ---------PREPARE THE ENVIRONMENT------------ #
  327. # PROCESS ARGUMENTS, OVERRIDE DEFAULTS
  328. for arg in "$@"; do
  329. process_option $arg
  330. done
  331. if [ $quiet -eq 1 ] && [ $never_venv -eq 0 ] && [ $always_venv -eq 0 ]
  332. then
  333. always_venv=1
  334. fi
  335. # If destroy is set, just blow it away and exit.
  336. if [ $destroy -eq 1 ]; then
  337. destroy_venv
  338. exit 0
  339. fi
  340. # Ignore all of this if the -N flag was set
  341. if [ $never_venv -eq 0 ]; then
  342. # Restore previous environment if desired
  343. if [ $restore_env -eq 1 ]; then
  344. restore_environment
  345. fi
  346. # Remove the virtual environment if --force used
  347. if [ $force -eq 1 ]; then
  348. destroy_venv
  349. fi
  350. # Then check if it's up-to-date
  351. environment_check
  352. # Create a backup of the up-to-date environment if desired
  353. if [ $backup_env -eq 1 ]; then
  354. backup_environment
  355. fi
  356. fi
  357. # ---------EXERCISE THE CODE------------ #
  358. # Run management commands
  359. if [ $manage -eq 1 ]; then
  360. run_management_command
  361. exit $?
  362. fi
  363. # Build the docs
  364. if [ $just_docs -eq 1 ]; then
  365. run_sphinx
  366. exit $?
  367. fi
  368. # PEP8
  369. if [ $just_pep8 -eq 1 ]; then
  370. run_pep8
  371. exit $?
  372. fi
  373. if [ $just_pep8_changed -eq 1 ]; then
  374. run_pep8_changed
  375. exit $?
  376. fi
  377. # Pylint
  378. if [ $just_pylint -eq 1 ]; then
  379. run_pylint
  380. exit $?
  381. fi
  382. # Tab checker
  383. if [ $just_tabs -eq 1 ]; then
  384. tab_check
  385. exit $?
  386. fi
  387. # Django development server
  388. if [ $runserver -eq 1 ]; then
  389. run_server
  390. exit $?
  391. fi
  392. # Full test suite
  393. run_tests || exit