{ "info": { "author": "Konrad Ha\u0142as", "author_email": "halas.konrad@gmail.com", "bugtrack_url": null, "classifiers": [ "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Testing" ], "description": "MutPy\n=====\n\n|Python Versions| |Build Status| |Coverage Status| |Code Climate|\n\nMutPy is a mutation testing tool for Python 3.3+ source code. MutPy\nsupports standard unittest module, generates YAML/HTML reports and has\ncolorful output. It applies mutation on AST level. You could boost your\nmutation testing process with high order mutations (HOM) and code\ncoverage analysis.\n\nMutation testing\n----------------\n\nFrom article at Wikipedia:\n\n **Mutation testing** (or Mutation analysis or Program mutation)\n evaluates the quality of software tests. Mutation testing involves\n modifying a program's source code or byte code in small ways. A test\n suite that does not detect and reject the mutated code is considered\n defective. These so-called mutations, are based on well-defined\n mutation operators that either mimic typical programming errors\n (such as using the wrong operator or variable name) or force the\n creation of valuable tests (such as driving each expression to\n zero). The purpose is to help the tester develop effective tests or\n locate weaknesses in the test data used for the program or in\n sections of the code that are seldom or never accessed during\n execution.\n\nInstallation\n------------\n\nYou can easily install MutPy from PyPi:\n\n::\n\n $ pip install mutpy\n\n... or if you want to have latest changes you can clone this repository\nand install MutPy from sources:\n\n::\n\n $ git clone git@github.com:mutpy/mutpy.git\n $ cd mutpy/\n $ python3 setup.py install\n\nExample\n-------\n\nMain code (``calculator.py``) - we will mutate it:\n\n.. code:: python\n\n def mul(x, y):\n return x * y\n\nTest (``test_calculator.py``) - we will check its quality:\n\n.. code:: python\n\n from unittest import TestCase\n from calculator import mul\n\n class CalculatorTest(TestCase):\n\n def test_mul(self):\n self.assertEqual(mul(2, 2), 4)\n\nNow we can run MutPy in the same directory where we have our sources\nfiles:\n\n::\n\n $ mut.py --target calculator --unit-test test_calculator -m\n\nThis command will produce the following output:\n\n::\n\n [*] Start mutation process:\n - targets: calculator\n - tests: test_calculator\n [*] All tests passed:\n - test_calculator [0.00031 s]\n [*] Start mutants generation and execution:\n - [# 1] AOR calculator.py:2 :\n --------------------------------------------------------------------------------\n 1: def mul(x, y):\n ~2: return x / y\n --------------------------------------------------------------------------------\n [0.02944 s] killed by test_mul (test_calculator.CalculatorTest)\n - [# 2] AOR calculator.py:2 :\n --------------------------------------------------------------------------------\n 1: def mul(x, y):\n ~2: return x // y\n --------------------------------------------------------------------------------\n [0.02073 s] killed by test_mul (test_calculator.CalculatorTest)\n - [# 3] AOR calculator.py:2 :\n --------------------------------------------------------------------------------\n 1: def mul(x, y):\n ~2: return x ** y\n --------------------------------------------------------------------------------\n [0.01152 s] survived\n - [# 4] SDL calculator.py:2 :\n --------------------------------------------------------------------------------\n 1: def mul(x, y):\n ~2: pass\n --------------------------------------------------------------------------------\n [0.01437 s] killed by test_mul (test_calculator.CalculatorTest)\n [*] Mutation score [0.21818 s]: 75.0%\n - all: 4\n - killed: 3 (75.0%)\n - survived: 1 (25.0%)\n - incompetent: 0 (0.0%)\n - timeout: 0 (0.0%)\n\nFirst of all we run MutPy with few parameters. The most important are:\n\n- ``--target`` - after this flag we should pass module which we want to\n mutate.\n- ``--unit-test`` - this flag point to our unit tests module.\n\nThere are few phases in mutation process which we can see on printed by\nMutPy output (marked by star ``[*]``):\n\n- main code and tests modules loading,\n- run tests with original (not mutated) code base,\n- code mutation (main mutation phase),\n- results summary.\n\nThere are 4 mutants generated in main mutation phase - 3 of them are\nkilled and only 1 mutant survived. We can see all stats at the end of\nMutPy output. In this case MutPy didn't generate any incompetent (raised\n``TypeError``) and timeout (generated infinite loop) mutants. Our\nmutation score (killed to all mutants ratio) is 75%.\n\nTo increase mutation score (100% is our target) we need to improve our\ntests. This is a mutant which survived:\n\n.. code:: python\n\n def mul(x, y):\n return x ** y\n\nThis mutant survived because our test check if ``2 * 2 == 4``. Also\n``2 ** 2 == 4``, so this data aren't good to specify multiplication\noperation. We should change it, eg:\n\n.. code:: python\n\n from unittest import TestCase\n from calculator import mul\n\n class CalculatorTest(TestCase):\n\n def test_mul(self):\n self.assertEqual(mul(2, 3), 6)\n\nWe can run MutPy again and now mutation score is equal 100%.\n\nCommand-line arguments\n----------------------\n\nList of all arguments with which you can run MutPy:\n\n- ``-t TARGET [TARGET ...]``, ``--target TARGET [TARGET ...]`` - target\n module or package to mutate,\n- ``-u UNIT_TEST [UNIT_TEST ...]``,\n ``--unit-test UNIT_TEST [UNIT_TEST ...]`` - test class, test method,\n module or package with unit tests,\n- ``--runner RUNNER`` - currently supported are: unittest (default), pytest (experimental)\n- ``-m``, ``--show-mutants`` - show mutants source code,\n- ``-r REPORT_FILE``, ``--report REPORT_FILE`` - generate YAML report,\n- ``--report-html DIR_NAME`` - generate HTML report,\n- ``-f TIMEOUT_FACTOR``. ``--timeout-factor TIMEOUT_FACTOR`` - max\n timeout factor (default 5),\n- ``-d``, ``--disable-stdout`` - try disable stdout during mutation\n (this option can damage your tests if you interact with\n ``sys.stdout``),\n- ``-e``. ``--experimental-operators`` - use experimental operators,\n- ``-o OPERATOR [OPERATOR ...]``,\n ``--operator OPERATOR [OPERATOR ...]`` - use only selected operators,\n- ``--disable-operator OPERATOR [OPERATOR ...]`` - disable selected\n operators,\n- ``-l``. ``--list-operators`` - list available operators,\n- ``-p DIR``. ``--path DIR`` - extend Python path,\n- ``--percentage PERCENTAGE`` - percentage of the generated mutants\n (mutation sampling),\n- ``--coverage`` - mutate only covered code,\n- ``-h``, ``--help`` - show this help message and exit,\n- ``-v``, ``--version`` - show program's version number and exit,\n- ``-q``, ``--quiet`` - quiet mode,\n- ``--debug`` - debug mode,\n- ``-c``. ``--colored-output`` - try print colored output,\n- ``--order ORDER`` - mutation order,\n- ``--hom-strategy HOM_STRATEGY`` - HOM strategy,\n- ``--list-hom-strategies`` - list available HOM strategies,\n- ``--mutation-number MUTATION_NUMBER`` - run only one mutation (debug\n purpose).\n\nMutation operators\n------------------\n\nList of MutPy mutation operators sorted by alphabetical order:\n\n- AOD - arithmetic operator deletion\n- AOR - arithmetic operator replacement\n- ASR - assignment operator replacement\n- BCR - break continue replacement\n- COD - conditional operator deletion\n- COI - conditional operator insertion\n- CRP - constant replacement\n- DDL - decorator deletion\n- EHD - exception handler deletion\n- EXS - exception swallowing\n- IHD - hiding variable deletion\n- IOD - overriding method deletion\n- IOP - overridden method calling position change\n- LCR - logical connector replacement\n- LOD - logical operator deletion\n- LOR - logical operator replacement\n- ROR - relational operator replacement\n- SCD - super calling deletion\n- SCI - super calling insert\n- SIR - slice index remove\n\nExperimental mutation operators:\n\n- CDI - classmethod decorator insertion\n- OIL - one iteration loop\n- RIL - reverse iteration loop\n- SDI - staticmethod decorator insertion\n- SDL - statement deletion\n- SVD - self variable deletion\n- ZIL - zero iteration loop\n\nSupported Test Runners\n----------------------\n\nCurrently the following test runners are supported by MutPy:\n\n- `unittest `_\n- `pytest `_\n\nLicense\n-------\n\nLicensed under the Apache License, Version 2.0. See LICENSE file.\n\nMutPy was developed as part of engineer's and master\u2019s thesis at\nInstitute of Computer Science, Faculty of Electronics and Information\nTechnology, Warsaw University of Technology.\n\n.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/MutPy.svg\n :target: https://github.com/mutpy/mutpy\n.. |Build Status| image:: https://travis-ci.org/mutpy/mutpy.svg?branch=master\n :target: https://travis-ci.org/mutpy/mutpy\n.. |Coverage Status| image:: https://coveralls.io/repos/github/mutpy/mutpy/badge.svg?branch=master\n :target: https://coveralls.io/github/mutpy/mutpy?branch=master\n.. |Code Climate| image:: https://codeclimate.com/github/mutpy/mutpy/badges/gpa.svg\n :target: https://codeclimate.com/github/mutpy/mutpy\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/mutpy/mutpy", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mutpy/mutpy", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "MutPy", "package_url": "https://pypi.org/project/MutPy/", "platform": "", "project_url": "https://pypi.org/project/MutPy/", "project_urls": { "Download": "https://github.com/mutpy/mutpy", "Homepage": "https://github.com/mutpy/mutpy" }, "release_url": "https://pypi.org/project/MutPy/0.6.0/", "requires_dist": [ "Jinja2 (>=2.7.1)", "termcolor (>=1.0.0)", "astmonkey (>=0.2.2)", "PyYAML (<=3.11,>=3.10) ; python_version <= \"3.3\"", "PyYAML (>=3.10) ; python_version > \"3.3\"", "pytest (>=3.0) ; extra == 'pytest'" ], "requires_python": ">=3.3", "summary": "Mutation testing tool for Python 3.x source code.", "version": "0.6.0" }, "last_serial": 5151804, "releases": { "0.3.0": [ { "comment_text": "", "digests": { "md5": "c855d122ef2c43bb297a3b0711ba9ea3", "sha256": "bd9fb6caeed25673d9ac3537ecf1daecf8932709eccfa86de3f94d5f86b847b8" }, "downloads": -1, "filename": "MutPy-0.3.0.tar.gz", "has_sig": false, "md5_digest": "c855d122ef2c43bb297a3b0711ba9ea3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14985, "upload_time": "2012-04-22T17:21:23", "url": "https://files.pythonhosted.org/packages/9e/88/c5e5cb013f62fc4025894aaaf3666c7e74e66a6dade2e6f01dce883b33dc/MutPy-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "cfd5f01c472834c191700453086b4c07", "sha256": "7c687fb577c88b4f304565ae84000bfbef63ff7fe70b1351e2e6f36f8e756ebd" }, "downloads": -1, "filename": "MutPy-0.3.1.tar.gz", "has_sig": false, "md5_digest": "cfd5f01c472834c191700453086b4c07", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23348, "upload_time": "2013-09-24T21:19:02", "url": "https://files.pythonhosted.org/packages/e3/76/a5612b6a7bcc3cc0a9ca0727d75c88d9ef1f6b13d36a8d0725e434042c42/MutPy-0.3.1.tar.gz" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "2592ed63fe1e89571388a03a59c88d70", "sha256": "e006760ee90919f0e5b099b22a04fe2b358a8190abf220e53a682f8387d1a9f9" }, "downloads": -1, "filename": "MutPy-0.3.2.tar.gz", "has_sig": false, "md5_digest": "2592ed63fe1e89571388a03a59c88d70", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23333, "upload_time": "2013-09-24T21:24:11", "url": "https://files.pythonhosted.org/packages/b7/6a/8a498f5dd311c65d55336960bf580524965dc36ffc4f3e9638741c7d5549/MutPy-0.3.2.tar.gz" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "b77af5487be4f4e3bce51f41dcda7e2d", "sha256": "82234d1883be88d09076b08212b73157395fc8d95b88ee76c6a2cf8a848a0725" }, "downloads": -1, "filename": "MutPy-0.3.3.tar.gz", "has_sig": false, "md5_digest": "b77af5487be4f4e3bce51f41dcda7e2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23644, "upload_time": "2013-12-08T19:47:58", "url": "https://files.pythonhosted.org/packages/29/17/e7195b52812bdd2a44984ed20ef37219fee4bb12374a3baf2ba85285c69e/MutPy-0.3.3.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "6a31e3babbb872029458e63ef01cc5f1", "sha256": "d0e348e3c00f6bfafa5287035edac74bda09475bc06d62980fed62203124e969" }, "downloads": -1, "filename": "MutPy-0.4.0.tar.gz", "has_sig": false, "md5_digest": "6a31e3babbb872029458e63ef01cc5f1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24323, "upload_time": "2013-12-31T11:07:57", "url": "https://files.pythonhosted.org/packages/6e/5e/6ab44c9b59ccfc5337845bd177d277804df2b50f03c7d55e258230ce3b8a/MutPy-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "b5dc2f24666519a4ebde9b1e8ae1b202", "sha256": "c2437018cf69980279be84853c91cb64de9f33b464578e89f48da62720d34a2a" }, "downloads": -1, "filename": "MutPy-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "b5dc2f24666519a4ebde9b1e8ae1b202", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 31395, "upload_time": "2017-08-03T16:07:17", "url": "https://files.pythonhosted.org/packages/1f/2e/bb5128877b8c05e243445e83c0848563b3c47ee431cfaf1a6e819104fab7/MutPy-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f9e973ab0a0b557d81f1102538a3e6a2", "sha256": "ea6de3c608c52e7e07c13a7cfc946cd7dc7d9ed79fb657d23bff2dd60f76dbf3" }, "downloads": -1, "filename": "MutPy-0.5.0.tar.gz", "has_sig": false, "md5_digest": "f9e973ab0a0b557d81f1102538a3e6a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27209, "upload_time": "2017-08-03T16:07:18", "url": "https://files.pythonhosted.org/packages/84/db/5ac6f2801461906add5494df416ca466651211889bc903fa9f521ea4879d/MutPy-0.5.0.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "0a948ffb13f385c973c8bf6eedf27728", "sha256": "267f2acaaa99484c6d828b01d08acde49c63ba3765cd5316cdc553eb85cef026" }, "downloads": -1, "filename": "MutPy-0.5.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0a948ffb13f385c973c8bf6eedf27728", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 31366, "upload_time": "2017-08-08T09:20:02", "url": "https://files.pythonhosted.org/packages/12/fc/3a4fb6ccad4437c6cf7f7b5f888fec55108a4bc2438b1af8152b9f1b0d08/MutPy-0.5.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "21bcd589ff80e2ab4d2704ecc31f1bd3", "sha256": "734cf4c2fe4192fb775173af42e44afa97f28d16879b43dbdb3a876f419498cf" }, "downloads": -1, "filename": "MutPy-0.5.1.tar.gz", "has_sig": false, "md5_digest": "21bcd589ff80e2ab4d2704ecc31f1bd3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27207, "upload_time": "2017-08-08T09:20:04", "url": "https://files.pythonhosted.org/packages/b0/46/d8d3fb238896d28cd1a849ee60c13bbf2cbf5aac8d634f3df26c5f8f0b49/MutPy-0.5.1.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "45554d631ec445ec9cbdbea9a726204d", "sha256": "6f8f03114c2ed84f508415a07d62194653d11d1c7483df6ea6d2c43929fb16a6" }, "downloads": -1, "filename": "MutPy-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "45554d631ec445ec9cbdbea9a726204d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.3", "size": 33436, "upload_time": "2019-04-16T19:36:28", "url": "https://files.pythonhosted.org/packages/84/be/6b2d1b64b23a36058453f84bdc7e86b615b9678b3c4d1a7984a6af1ceba6/MutPy-0.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d1c8d64be704dabcb6d7f4a81bda6673", "sha256": "2081c38063e7d874bcf2f42a94b54dd9d6adc5075870a9469b3b95e540ffd099" }, "downloads": -1, "filename": "MutPy-0.6.0.tar.gz", "has_sig": false, "md5_digest": "d1c8d64be704dabcb6d7f4a81bda6673", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.3", "size": 28622, "upload_time": "2019-04-16T19:36:29", "url": "https://files.pythonhosted.org/packages/09/92/a90b8e022b8f4fae22c541705cbcfbf5c0c8fd1653cf5a66962ef0c0f3bc/MutPy-0.6.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "45554d631ec445ec9cbdbea9a726204d", "sha256": "6f8f03114c2ed84f508415a07d62194653d11d1c7483df6ea6d2c43929fb16a6" }, "downloads": -1, "filename": "MutPy-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "45554d631ec445ec9cbdbea9a726204d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.3", "size": 33436, "upload_time": "2019-04-16T19:36:28", "url": "https://files.pythonhosted.org/packages/84/be/6b2d1b64b23a36058453f84bdc7e86b615b9678b3c4d1a7984a6af1ceba6/MutPy-0.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d1c8d64be704dabcb6d7f4a81bda6673", "sha256": "2081c38063e7d874bcf2f42a94b54dd9d6adc5075870a9469b3b95e540ffd099" }, "downloads": -1, "filename": "MutPy-0.6.0.tar.gz", "has_sig": false, "md5_digest": "d1c8d64be704dabcb6d7f4a81bda6673", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.3", "size": 28622, "upload_time": "2019-04-16T19:36:29", "url": "https://files.pythonhosted.org/packages/09/92/a90b8e022b8f4fae22c541705cbcfbf5c0c8fd1653cf5a66962ef0c0f3bc/MutPy-0.6.0.tar.gz" } ] }