undercover.el-0.6.1/0000755000175000017500000000000013102127762014124 5ustar dogslegdogslegundercover.el-0.6.1/LICENSE0000644000175000017500000000207613102127762015136 0ustar dogslegdogslegThe MIT License (MIT) Copyright (c) 2014 Sviridov Alexander Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. undercover.el-0.6.1/Cask0000644000175000017500000000026613102127762014734 0ustar dogslegdogsleg(source gnu) (source melpa) (package-file "undercover.el") (files "*.el") (depends-on "dash") (depends-on "shut-up") (development (depends-on "ert-runner") (depends-on "s")) undercover.el-0.6.1/README.md0000644000175000017500000000714013102127762015405 0ustar dogslegdogsleg# undercover.el [![Coverage Status](https://coveralls.io/repos/sviridov/undercover.el/badge.svg)](https://coveralls.io/r/sviridov/undercover.el?branch=master) [![Build Status](https://travis-ci.org/sviridov/undercover.el.svg)](https://travis-ci.org/sviridov/undercover.el) [![license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/sviridov/undercover.el/blob/master/LICENSE) [![MELPA](http://melpa.org/packages/undercover-badge.svg)](http://melpa.org/#/undercover) [![MELPA stable](http://stable.melpa.org/packages/undercover-badge.svg)](http://stable.melpa.org/#/undercover) A test coverage library for [Emacs Lisp](http://www.gnu.org/software/emacs/manual/html_node/elisp/index.html). ## Notes Few important notes about `undercover.el`: - it assumes a certain development cycle of your package (using [Cask](https://github.com/cask/cask), [Travis CI](https://travis-ci.org/) and [Coveralls](https://coveralls.io/)); - it doesn't support test coverage for byte-compiled files; - it based on `edebug` and can have some issues with macros coverage. It doesn't support [Circular Objects](http://www.gnu.org/software/emacs/manual/html_node/elisp/Circular-Objects.html). Check out [combined usage example](https://github.com/sviridov/undercover.el-combined-usage-example) and [buttercup integration example](https://github.com/sviridov/undercover.el-buttercup-integration-example) for more information. ## Installation - Add `undercover.el` to your [Cask](https://github.com/cask/cask) file: ```lisp (source gnu) (source melpa) (package-file "awesome-package.el") (development (depends-on "undercover")) ``` - Before `load` or `require` your package in `test/test-helper.el` or `features/support/env.el` (or analogue), call `undercover` with wildcards that will match package files: ```lisp (when (require 'undercover nil t) (undercover "*.el" "awesome-extensions/*.el" (:exclude "awesome-examples.el"))) (require 'awesome-package) ``` - Add your repository to [Coveralls](https://coveralls.io/). ## Configuration - If you don't use [Travis CI](https://travis-ci.org/) you need to set `COVERALLS_REPO_TOKEN` environment variable before running tests, for example: ```sh $ COVERALLS_REPO_TOKEN= cask exec ert-runner ``` - Set `report-file` option if you want to change report location: ```lisp (undercover "*.el" (:report-file "/tmp/local-report.json")) ``` `undercover.el` will try to merge new report with existing one. - Set `send-report` option to `nil` if you don't want to send coverage report: ```lisp (undercover "*.el" (:report-file "/tmp/local-report.json") (:send-report nil)) ``` - Set `UNDERCOVER_FORCE` environment variable if you want to do coverage calculation locally: ```sh UNDERCOVER_FORCE=true cask exec ert-runner ``` - Set `UNDERCOVER_CONFIG` if you want to configure `undercover.el` via environment variables: ```lisp (when (require 'undercover nil t) (undercover)) ``` ```sh $ UNDERCOVER_CONFIG='("*.el" (:exclude "awesome-examples.el"))' cask exec ert-runner ``` - If you get `"UNDERCOVER: No coverage information [...]"`, make sure of the following: 1. remove byte-compiled files (`*.elc`) of your project 2. load and configure undercover before your project files (see above) 3. make sure ert-runner does not load your project files (your project's `.ert-runner` should use `-L` instead of `-l` for files you want to measure coverage of) - If you want to measure code coverage locally, you can set `TRAVIS=true` in the shell environment or `(setq undercover-force-coverage t)` in emacs. undercover.el-0.6.1/undercover.el0000644000175000017500000004674513102127762016642 0ustar dogslegdogsleg;;; undercover.el --- Test coverage library for Emacs Lisp -*- lexical-binding: t -*- ;; Copyright (c) 2014 Sviridov Alexander ;; Author: Sviridov Alexander ;; URL: https://github.com/sviridov/undercover.el ;; Created: Sat Sep 27 2014 ;; Keywords: lisp, tests, coverage, tools ;; Version: 0.6.1 ;; Package-Requires: ((emacs "24") (dash "2.0.0") (shut-up "0.3.2")) ;;; Commentary: ;; Provides a test coverage tools for Emacs packages. ;;; Code: (eval-when-compile (require 'cl)) (require 'edebug) (require 'json) (require 'dash) (require 'shut-up) (defconst undercover-version "0.6.1") (defvar undercover-force-coverage nil "If nil, test coverage check will be done only under continuous integration service.") (defvar undercover--send-report t "If not nil, test coverage report will be sent to coveralls.io.") (defvar undercover--report-file-path "/tmp/undercover_coveralls_report" "Path to save coveralls.io report.") (defvar undercover--files nil "List of files for test coverage check.") (defvar undercover--files-coverage-statistics (make-hash-table :test 'equal) "Table of coverage statistics for each file in `undercover--files'.") (defvar undercover--old-edebug-make-form-wrapper (symbol-function 'edebug-make-form-wrapper)) ;; Utilities (defun undercover--fill-hash-table (hash-table &rest keys-and-values) "Fill HASH-TABLE from KEYS-AND-VALUES." (loop for (key value) on keys-and-values by #'cddr do (puthash key value hash-table)) hash-table) (defun undercover--make-hash-table (&rest keys-and-values) "Create new hash-table and fill it from KEYS-AND-VALUES." (apply #'undercover--fill-hash-table (make-hash-table :test 'equal) keys-and-values)) (defun undercover--wildcards-to-files (wildcards) "Return list of files matched by WILDCARDS. Example of WILDCARDS: (\"*.el\" \"subdir/*.el\" (:exclude \"exclude-*.el\"))." (destructuring-bind (exclude-clauses include-wildcards) (--separate (and (consp it) (eq :exclude (car it))) wildcards) (let* ((exclude-wildcards (-mapcat #'cdr exclude-clauses)) (exclude-files (-mapcat #'file-expand-wildcards exclude-wildcards)) (include-files (-mapcat #'file-expand-wildcards include-wildcards))) (-difference include-files exclude-files)))) ;; `edebug' related functions and hacks: ;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6415 (def-edebug-spec cl-destructuring-bind (sexp form body)) (def-edebug-spec destructuring-bind (sexp form body)) (def-edebug-spec cl-symbol-macrolet ((&rest (symbolp sexp)) cl-declarations body)) (def-edebug-spec symbol-macrolet ((&rest (symbolp sexp)) cl-declarations body)) (def-edebug-spec cl-type-spec sexp) (def-edebug-spec when-let ([&or (symbolp form) (&rest (symbolp form))] body)) (defun undercover--fallback-file-handler (operation args) "Handle any file OPERATION with ARGS." (let ((inhibit-file-name-handlers (cons 'undercover-file-handler (and (eq inhibit-file-name-operation operation) inhibit-file-name-handlers))) (inhibit-file-name-operation operation)) (apply operation args))) (defun undercover--load-file-handler (file) "Handle `load' FILE operation." (let ((edebug-all-defs (undercover--coverage-enabled-p)) (load-file-name (file-truename file)) (load-in-progress t)) (unwind-protect (progn (save-excursion (eval-buffer (find-file load-file-name))) (push load-file-name undercover--files)) (switch-to-buffer (current-buffer))))) (defun undercover--show-load-file-error (filename) (message "UNDERCOVER: error while covering %s" filename) (message "UNDERCOVER: please open a new issue at https://github.com/sviridov/undercover.el/issues")) (defun undercover-file-handler (operation &rest args) "Handle `load' OPERATION. Ignore all ARGS except first." (if (eq 'load operation) (condition-case nil (undercover--load-file-handler (car args)) (error (undercover--show-load-file-error (car args)) (undercover--fallback-file-handler operation args))) (undercover--fallback-file-handler operation args))) (defun undercover--edebug-files (files) "Use `edebug' package to instrument all macros and functions in FILES." (when files (let ((regexp (->> files (regexp-opt) (format "/%s$")))) (add-to-list 'file-name-handler-alist (cons regexp 'undercover-file-handler))))) (setf (symbol-function 'undercover--stop-point-before) (lambda (before-index) "Increase number of times that stop point at BEFORE-INDEX was covered." (when (boundp 'edebug-freq-count) (incf (aref edebug-freq-count before-index))) before-index)) (setf (symbol-function 'undercover--stop-point-after) (cons 'macro (lambda (before-index after-index form) "Increase number of times that stop point at AFTER-INDEX was covered." `(let ((before-index ,before-index) (after-index ,after-index)) (unwind-protect ,form (when (boundp 'edebug-freq-count) (aset edebug-freq-count after-index (+ 1 (aref edebug-freq-count after-index))) (undercover--align-counts-between-stop-points before-index after-index))))))) (setf (symbol-function 'undercover--align-counts-between-stop-points) (lambda (before-index after-index) "Decrease number of times that stop points between BEFORE-INDEX and AFTER-INDEX are covered." (do ((index (1+ before-index) (1+ index))) ((>= index after-index)) (setf (aref edebug-freq-count index) (min (aref edebug-freq-count index) (aref edebug-freq-count before-index)))))) (defun undercover--stop-points (name) "Return stop points ordered by position for NAME." (append (nth 2 (get name 'edebug)) nil)) (defun undercover--stop-points-covers (name) "Return number of covers for each stop point ordered by position for NAME." (append (get name 'edebug-freq-count) nil)) (defun undercover--shut-up-edebug-message () "Muffle `edebug' message \"EDEBUG: function\"." ;; HACK: I don't use `defadvice' because of cryptic error with `shut-up-sink'. ;; https://travis-ci.org/sviridov/multiple-cursors.el/builds/37529750#L1387 ;; https://travis-ci.org/sviridov/expand-region.el/builds/37576813#L285 (setf (symbol-function 'edebug-make-form-wrapper) (lambda (&rest args) (shut-up (apply undercover--old-edebug-make-form-wrapper args))))) (defun undercover--set-edebug-handlers () "Replace and advice some `edebug' functions with `undercover' handlers." (defalias 'edebug-before 'undercover--stop-point-before) (defalias 'edebug-after 'undercover--stop-point-after) (undercover--shut-up-edebug-message) ;; HACK: Ensures that debugger is turned off. ;; https://travis-ci.org/sviridov/multiple-cursors.el/builds/37672312#L350 ;; https://travis-ci.org/sviridov/expand-region.el/builds/37577423#L336 (setq debug-on-error nil debug-on-signal nil edebug-on-error nil)) ;; Coverage statistics related functions: (defun undercover--symbol-coverage-statistics (edebug-symbol statistics) "Collect coverage statistics for EDEBUG-SYMBOL into STATISTICS hash." (let* ((start-marker (car (get edebug-symbol 'edebug))) (points (undercover--stop-points edebug-symbol)) (points-covers (undercover--stop-points-covers edebug-symbol)) (points-and-covers (map 'list #'cons points points-covers))) (dolist (point-and-cover points-and-covers) (let* ((point (car point-and-cover)) (line (line-number-at-pos (+ point start-marker))) (cover (cdr point-and-cover)) (previous-score (gethash line statistics cover)) (new-score (min previous-score cover))) (puthash line new-score statistics))))) (defun undercover--file-coverage-statistics () "Collect coverage statistics for current-file into hash. Keys of that hash are line numbers. Values of that hash are number of covers." (let ((statistics (make-hash-table))) (dolist (edebug-data edebug-form-data) (let ((edebug-symbol (car edebug-data))) (when (get edebug-symbol 'edebug) (undercover--symbol-coverage-statistics edebug-symbol statistics)))) statistics)) (defun undercover--collect-file-coverage (file) "Collect coverage statistics for FILE." (save-excursion (find-file file) (if edebug-form-data (undercover--fill-hash-table undercover--files-coverage-statistics file (undercover--file-coverage-statistics)) (setq undercover--files (delq file undercover--files))))) (defun undercover--collect-files-coverage (files) "Collect coverage statistics for each file in FILES." (dolist (file files) (undercover--collect-file-coverage file))) ;; Continuous integration related functions: (defun undercover--under-travic-ci-p () "Check that `undercover' running under Travis CI service." (getenv "TRAVIS")) (defun undercover--coveralls-repo-token () "Return coveralls.io repo token provided by user." (getenv "COVERALLS_REPO_TOKEN")) (defun undercover--under-ci-p () "Check that `undercover' running under continuous integration service." (or (undercover--coveralls-repo-token) (undercover--under-travic-ci-p) (getenv "UNDERCOVER_FORCE"))) ;;; Reports related functions: (defun undercover--determine-report-type () "Automatic report-type determination." (and (undercover--under-ci-p) 'coveralls)) (defun undercover--get-git-info (&rest args) "Execute Git with ARGS, returning the first line of its output." (with-temp-buffer (apply #'process-file "git" nil t nil "--no-pager" args) (goto-char (point-min)) (buffer-substring-no-properties (line-beginning-position) (line-end-position)))) (defun undercover--get-git-info-from-log (format) "Get first line of Git log in given FORMAT." (undercover--get-git-info "log" "-1" (format "--pretty=format:%%%s" format))) (defun undercover--get-git-remotes () "Return list of Git remotes." (with-temp-buffer (process-file "git" nil t nil "--no-pager" "remote") (let ((remotes (split-string (buffer-string) "\n" t)) (config-path-format (format "remote.%%s.url")) (remotes-info nil)) (dolist (remote remotes remotes-info) (let* ((remote-url (undercover--get-git-info "config" (format config-path-format remote))) (remote-table (undercover--make-hash-table "name" remote "url" remote-url))) (push remote-table remotes-info)))))) ;; coveralls.io report: (defun undercover--update-coveralls-report-with-repo-token (report) "Update test coverage REPORT for coveralls.io with repository token." (puthash "repo_token" (undercover--coveralls-repo-token) report)) (defun undercover--try-update-coveralls-report-with-shippable (report) "Update test coverage REPORT for coveralls.io with Shippable service information." (when (getenv "SHIPPABLE") (undercover--fill-hash-table report "service_name" "shippable" "service_job_id" (getenv "BUILD_NUMBER")) (unless (string-equal "false" (getenv "PULL_REQUEST")) (undercover--fill-hash-table report "service_pull_request" (getenv "PULL_REQUEST"))))) (defun undercover--update-coveralls-report-with-travis-ci (report) "Update test coverage REPORT for coveralls.io with Travis CI service information." (undercover--fill-hash-table report "service_name" "travis-ci" "service_job_id" (getenv "TRAVIS_JOB_ID"))) (defun undercover--update-coveralls-report-with-git (report) "Update test coverage REPORT for coveralls.io with Git information." (undercover--fill-hash-table report "git" (undercover--make-hash-table "branch" (undercover--get-git-info "rev-parse" "--abbrev-ref" "HEAD") "remotes" (undercover--get-git-remotes) "head" (undercover--make-hash-table "id" (undercover--get-git-info-from-log "H") "author_name" (undercover--get-git-info-from-log "aN") "author_email" (undercover--get-git-info-from-log "ae") "committer_name" (undercover--get-git-info-from-log "cN") "committer_email" (undercover--get-git-info-from-log "ce") "message" (undercover--get-git-info-from-log "s"))))) (defun undercover--coveralls-file-coverage-report (statistics) "Translate file coverage STATISTICS into coveralls.io format." (let (file-coverage) (dotimes (line (count-lines (point-min) (point-max))) (push (gethash (1+ line) statistics) file-coverage)) (nreverse file-coverage))) (defun undercover--coveralls-file-report (file) "Create part of coveralls.io report for FILE." (save-excursion (find-file file) (let ((file-name (file-relative-name file (locate-dominating-file default-directory ".git"))) (file-content (buffer-substring-no-properties (point-min) (point-max))) (coverage-report (undercover--coveralls-file-coverage-report (gethash file undercover--files-coverage-statistics)))) (undercover--make-hash-table "name" file-name "source" file-content "coverage" coverage-report)))) (defun undercover--fill-coveralls-report (report) "Fill test coverage REPORT for coveralls.io." (undercover--fill-hash-table report "source_files" (mapcar #'undercover--coveralls-file-report undercover--files))) (defun undercover--merge-coveralls-report-file-lines-coverage (old-coverage new-coverage) "Merge test coverage for lines from OLD-COVERAGE and NEW-COVERAGE." (loop for (old-line-coverage . new-line-coverage) in (-zip-fill 0 old-coverage new-coverage) collect (cond ((null old-line-coverage) new-line-coverage) ((null new-line-coverage) old-line-coverage) (t (+ new-line-coverage old-line-coverage))))) (defun undercover--merge-coveralls-report-file-coverage (old-file-hash source-files-report) "Merge test coverage from OLD-FILE-HASH into SOURCE-FILES-REPORT." (let* ((file-name (gethash "name" old-file-hash)) (old-coverage (gethash "coverage" old-file-hash)) (new-file-hash (--first (string-equal file-name (gethash "name" it)) source-files-report))) (if new-file-hash (undercover--fill-hash-table new-file-hash "coverage" (undercover--merge-coveralls-report-file-lines-coverage old-coverage (gethash "coverage" new-file-hash))) (rplacd (last source-files-report) (cons old-file-hash nil))))) (defun undercover--merge-coveralls-reports (report) "Merge test coverage REPORT with existing from `undercover--report-file-path'." (ignore-errors (let* ((json-object-type 'hash-table) (json-array-type 'list) (old-report (json-read-file undercover--report-file-path)) (new-source-files-report (gethash "source_files" report))) (dolist (old-file-hash (gethash "source_files" old-report)) (undercover--merge-coveralls-report-file-coverage old-file-hash new-source-files-report))))) (defun undercover--create-coveralls-report () "Create test coverage report for coveralls.io." (undercover--collect-files-coverage undercover--files) (let ((report (make-hash-table :test 'equal))) (cond ((undercover--coveralls-repo-token) (undercover--update-coveralls-report-with-repo-token report) (undercover--try-update-coveralls-report-with-shippable report)) ((undercover--under-travic-ci-p) (undercover--update-coveralls-report-with-travis-ci report)) (t (unless (getenv "UNDERCOVER_FORCE") (error "Unsupported coveralls.io report")))) (undercover--update-coveralls-report-with-git report) (undercover--fill-coveralls-report report) (undercover--merge-coveralls-reports report) (json-encode report))) (defun undercover--save-coveralls-report (json-report) "Save JSON-REPORT to `undercover--report-file-path'." (save-excursion (shut-up (find-file undercover--report-file-path) (erase-buffer) (insert json-report) (save-buffer)))) (defun undercover--send-coveralls-report () "Send report to coveralls.io." (let ((coveralls-url "https://coveralls.io/api/v1/jobs")) (message "Sending: report to coveralls.io") (shut-up (shell-command (format "curl -v --include --form json_file=@%s %s" undercover--report-file-path coveralls-url))) (message "Sending: OK"))) (defun undercover--coveralls-report () "Create and submit test coverage report to coveralls.io." (undercover--save-coveralls-report (undercover--create-coveralls-report)) (when undercover--send-report (undercover--send-coveralls-report))) ;; `ert-runner' related functions: (defun undercover-safe-report () "Version of `undercover-report' that ignore errors." (ignore-errors (undercover-report))) (defun undercover-report-on-kill () "Add `undercover-safe-report' to `kill-emacs-hook'." (add-hook 'kill-emacs-hook 'undercover-safe-report)) ;;; Main functions: (defun undercover--coverage-enabled-p () "Check that `undercover' is enabled." (or undercover-force-coverage (undercover--under-ci-p))) (defun undercover-report (&optional report-type) "Create and submit (if needed) test coverage report based on REPORT-TYPE. Posible values of REPORT-TYPE: coveralls." (if undercover--files (case (or report-type (undercover--determine-report-type)) (coveralls (undercover--coveralls-report)) (t (error "Unsupported report-type"))) (message "UNDERCOVER: No coverage information. Make sure that your files are not compiled?"))) (defun undercover--env-configuration () "Read configuration from UNDERCOVER_CONFIG." (let ((configuration (getenv "UNDERCOVER_CONFIG"))) (when configuration (condition-case nil (car (read-from-string configuration)) (error (error "UNDERCOVER: error while parsing configuration")))))) (defun undercover--set-options (configuration) "Read CONFIGURATION. Set `undercover--send-report' and `undercover--report-file-path'. Return wildcards." (destructuring-bind (wildcards options) (--separate (or (stringp it) (eq :exclude (car-safe it))) configuration) (dolist (option options wildcards) (case (car-safe option) (:report-file (setq undercover--report-file-path (cadr option))) (:send-report (setq undercover--send-report (cadr option))) (otherwise (error "Unsupported option: %s" option)))))) (defun undercover--setup (configuration) "Enable test coverage for files matched by CONFIGURATION." (when (undercover--coverage-enabled-p) (let ((env-configuration (undercover--env-configuration)) (default-configuration '("*.el"))) (undercover--set-edebug-handlers) (undercover-report-on-kill) (let ((wildcards (undercover--set-options (or (append configuration env-configuration) default-configuration)))) (undercover--edebug-files (undercover--wildcards-to-files wildcards)))))) ;;;###autoload (defmacro undercover (&rest configuration) "Enable test coverage for files matched by CONFIGURATION. Example of CONFIGURATION: (\"*.el\" \"subdir/*.el\" (:exclude \"exclude-*.el\")). If running under Travic CI automatically generate report on `kill-emacs' and send it to coveralls.io." `(undercover--setup (list ,@(--map (if (atom it) it `(list ,@it)) configuration)))) (provide 'undercover) ;;; undercover.el ends here undercover.el-0.6.1/.gitignore0000644000175000017500000000001013102127762016103 0ustar dogslegdogsleg/.cask/ undercover.el-0.6.1/test/0000755000175000017500000000000013102127762015103 5ustar dogslegdogslegundercover.el-0.6.1/test/first-example-library/0000755000175000017500000000000013102127762021325 5ustar dogslegdogslegundercover.el-0.6.1/test/first-example-library/first-example-library.el0000644000175000017500000000134413102127762026073 0ustar dogslegdogsleg;;; first-exanple-library.el --- undercover.el: Library for test coverage tests -*- lexical-binding: t; -*- ;; Copyright (c) 2014 Sviridov Alexander ;; Author: Sviridov Alexander ;;; Commentary: ;; Library for test coverage tests. ;;; Code: (defun distance (point-1 point-2) "Return distance between POINT-1 and POINT-2." (let ((x1 (car point-1)) (x2 (car point-2)) (y1 (cadr point-1)) (y2 (cadr point-2))) (sqrt (+ (expt (- x1 x2) 2) (expt (- y1 y2) 2))))) (defun fib (n) "Return N's Fibonacci number." (cond ((zerop n) 0) ((= n 1) 1) (t (+ (fib (- n 1)) (fib (- n 2)))))) (provide 'first-example-library) ;;; first-example-library.el ends here undercover.el-0.6.1/test/test-helper.el0000644000175000017500000000154713102127762017670 0ustar dogslegdogsleg;;; test-helper.el --- undercover.el: Unit-test setup -*- lexical-binding: t; -*- ;; Copyright (c) 2014 Sviridov Alexander ;; Author: Sviridov Alexander ;;; Commentary: ;; Test suite setup for ERT Runner. (require 'undercover) (require 's) ;;; Code: (let ((undercover-force-coverage t)) (undercover "undercover.el") (load "undercover.el")) (defadvice undercover-safe-report (around self-report activate) (let ((undercover--files (list (file-truename "undercover.el"))) (undercover--send-report t) (undercover--report-file-path "/tmp/undercover-coverage.json")) ad-do-it)) (message "Running tests on Emacs %s" emacs-version) (when (s-contains? "--win" (getenv "ERT_RUNNER_ARGS")) (defun ert-runner/run-tests-batch-and-exit (selector) (ert-run-tests-interactively selector))) ;;; test-helper.el ends here undercover.el-0.6.1/test/first-example-library-test.el0000644000175000017500000001141313102127762022624 0ustar dogslegdogsleg;;; first-example-library-test.el --- undercover.el: Unit-test suite -*- lexical-binding: t; -*- ;; Copyright (c) 2014 Sviridov Alexander ;; Author: Sviridov Alexander ;;; Commentary: ;; The unit test suite of undercover.el. ;;; Code: (defconst first-example-library-filename "test/first-example-library/first-example-library.el") (defconst first-example-library-report-file "/tmp/first-example-library-report.json") (defmacro with-env-variable (name value &rest body) "Set environment variable NAME to VALUE and evaluate BODY." `(let ((---old-env-var--- (getenv ,name))) (setenv ,name ,value) (unwind-protect (progn ,@body) (setenv ,name ---old-env-var---)))) (with-env-variable "TRAVIS" "true" (let ((undercover-force-coverage nil)) (undercover "test/first-example-library/*.el" (:report-file first-example-library-report-file) (:send-report nil)) (ignore-errors (delete-file first-example-library-report-file)) (add-to-list 'load-path (file-truename "test/first-example-library")) (require 'first-example-library))) (ert-deftest test-1/edebug-handlers-are-setted () (should (eq 'undercover--stop-point-before (symbol-function 'edebug-before))) (should (eq 'undercover--stop-point-after (symbol-function 'edebug-after)))) (ert-deftest test-2/result-is-correct () (should (= 1.0 (distance '(0 0) '(1 0)))) (should (= 5.0 (distance '(3 3) '(6 7)))) (should (= 0 (fib 0))) (should (= 1 (fib 1))) (should (= 8 (fib 6)))) (ert-deftest test-3/functions-are-covered () (should (get 'distance 'edebug)) (should (get 'fib 'edebug))) (ert-deftest test-4/check-distance-stop-points-number-of-covers () (dolist (stop-point-covers (undercover--stop-points-covers 'distance)) (should (= stop-point-covers 2)))) (ert-deftest test-5/check-coverage-statistics () (undercover--collect-files-coverage undercover--files) (let ((example-library-statistics (gethash (file-truename first-example-library-filename) undercover--files-coverage-statistics))) ;; distance statistics (dolist (line '(15 16 17 18 19 20)) (should (= 2 (gethash line example-library-statistics)))) (should-not (gethash 14 example-library-statistics)) (should-not (gethash 21 example-library-statistics)) ;; fib statistics (should (= 27 (gethash 24 example-library-statistics))) (should (= 27 (gethash 25 example-library-statistics))) (should (= 21 (gethash 26 example-library-statistics))) (should (= 12 (gethash 27 example-library-statistics))))) (ert-deftest test-6/check-environment-variables () (with-env-variable "TRAVIS" "true" (should (eq 'coveralls (undercover--determine-report-type))))) (ert-deftest test-7/check-coveralls-report () (with-env-variable "TRAVIS" "true" (ad-deactivate 'undercover-safe-report) (undercover-safe-report) (ad-activate 'undercover-safe-report)) (let* ((json-object-type 'hash-table) (json-array-type 'list) (report (json-read-file first-example-library-report-file))) (cl-flet ((check-lines-statistics (multiplier example-library-statistics) ;; distance statistics (dolist (line '(14 15 16 17 18 19)) (should (= (* multiplier 2) (nth line example-library-statistics)))) (should-not (nth 13 example-library-statistics)) (should-not (nth 20 example-library-statistics)) ;; fib statistics (should (= (* multiplier 27) (nth 23 example-library-statistics))) (should (= (* multiplier 27) (nth 24 example-library-statistics))) (should (= (* multiplier 21) (nth 25 example-library-statistics))) (should (= (* multiplier 12) (nth 26 example-library-statistics))))) (should (string-equal "travis-ci" (gethash "service_name" report))) (let ((file-report (car (gethash "source_files" report)))) (should (string-equal "test/first-example-library/first-example-library.el" (gethash "name" file-report))) (should (string-equal (save-excursion (find-file (file-truename "test/first-example-library/first-example-library.el")) (buffer-substring-no-properties (point-min) (point-max))) (gethash "source" file-report))) (check-lines-statistics 1 (gethash "coverage" file-report)) (undercover--merge-coveralls-reports report) (check-lines-statistics 2 (gethash "coverage" file-report)))))) (ert-deftest test-8/should-error () (with-env-variable "TRAVIS" nil (should-error (undercover-report)) (should-error (undercover--create-coveralls-report)))) ;;; first-example-library-test.el ends here undercover.el-0.6.1/.ert-runner0000644000175000017500000000000413102127762016220 0ustar dogslegdogsleg-L .undercover.el-0.6.1/.travis.yml0000644000175000017500000000054113102127762016235 0ustar dogslegdogsleglanguage: emacs-lisp sudo: no env: - EVM_EMACS=emacs-24.3-travis - EVM_EMACS=emacs-24.4-travis - EVM_EMACS=emacs-24.5-travis before_install: - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > travis.sh && source ./travis.sh - evm install "$EVM_EMACS" --use --skip install: - cask install script: - cask exec ert-runner