Repository: CleanCut/green

Issue:
Combine methode name and doc string in output
With `-vvv` the output gives the first line of the doc-string of each `test_*()` method like this

```
Green 3.3.0, Coverage 5.5, Python 3.9.2

buhtzology.tests.test_khq
  TestKHK
.   KHQ Question 1

```

When doing `-vv` the output is this.
```
buhtzology.tests.test_khq
  TestKHK
.   test_Q1

```

What I would prefer is to have an output combining the method name and the doc string like this:
```
Green 3.3.0, Coverage 5.5, Python 3.9.2

buhtzology.tests.test_khq
  TestKHK
.   test_Q1: KHQ Question 1

```

Maybe adding a `-vvvv`?

Discussion:

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f7b7ab0..78c6b30 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,9 +2,9 @@ name: CI
 
 on:
   push:
-    branches: [master]
+    branches: [main]
   pull_request:
-    branches: [master]
+    branches: [main]
 
 jobs:
   tests:
@@ -35,13 +35,12 @@ jobs:
         if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest'
 
       - name: Test
-        run: python -m green.cmdline -tvvv green
-        if: matrix.python-version != '3.9' || matrix.os != 'ubuntu-latest'
+        run: python -m green.cmdline -tvvvv green
 
       - name: Generate coverage
         run: |
           pip install --upgrade coveralls
-          ./g -tvvvr green
+          ./g -tvvvvr green
         if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest'
 
       - name: Coveralls
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7558bc1..b5cce2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Version 3.4.0
+#### 12 January 2021
+
+- Four levels of verbosity (`-vvvv` on the command line or `verbose=4` in the config) now displays the test method name _and_ the test method docstring. Resolves #252.
+
 # Version 3.3.0
 #### 15 July 2021
 
@@ -73,7 +78,7 @@
 
 - Fixed a hang that sometimes occurs in Python 3.8.0-3.8.2 due to a bug in upstream Python
   - Upstream bug report: https://bugs.python.org/issue39360
-  - Upstream fix in master: https://github.com/python/cpython/pull/19009
+  - Upstream fix in main: https://github.com/python/cpython/pull/19009
   - Upstream fix in 3.8 branch (Maybe gets included in 3.8.3?): https://github.com/python/cpython/pull/19023
 - Fixed behavior of raising SkipTest in a setUpClass class method on Python >= 3.8
 
@@ -294,7 +299,7 @@
 #### 26 April 2017
 
 - Added a page about the Udemy course
-  [Python Testing with Green](https://github.com/CleanCut/green/blob/master/PythonTestingWithGreen.md),
+  [Python Testing with Green](https://github.com/CleanCut/green/blob/main/PythonTestingWithGreen.md),
   with lots of nice coupons and discount codes just for finding the Github
   page.  Check it out!
 
diff --git a/Makefile b/Makefile
index d58b57d..1415997 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ test-local:
 test-coverage:
 	@# Generate coverage files for travis builds (don't clean after this!)
 	@make clean-silent
-	./g 3 -r -vvv green
+	./g 3 -r -vvvv green
 	@echo "\n(test-coverage) completed\n"
 
 test-installed:
@@ -44,7 +44,7 @@ test-installed:
 	source venv-installed/bin/activate; python3 setup.py sdist
 	tar zxvf dist/green-$(VERSION).tar.gz
 	source venv-installed/bin/activate; cd green-$(VERSION) && python3 setup.py install
-	source venv-installed/bin/activate; green -vvv green
+	source venv-installed/bin/activate; green -vvvv green
 	@rm -rf venv-installed
 	@make clean-silent
 	@echo "\n(test-installed) completed\n"
@@ -61,8 +61,8 @@ sanity-checks:
 	@./g 3 -m 100 green
 	@# If there's already a tag for this version, then we forgot to bump the version.
 	@if git show-ref --verify --quiet refs/tags/$(VERSION) ; then printf "\nVersion $(VERSION) has already been tagged.\nIf the make process died after tagging, but before actually releasing, you can try 'make release-unsafe'\n\n" ; exit 1 ; fi
-	@# We should be on the master branch
-	@if [[ $(shell git rev-parse --abbrev-ref HEAD) != "master" ]] ; then echo "\nYou need to be on the master branch to release.\n" && exit 1 ; fi
+	@# We should be on the main branch
+	@if [[ $(shell git rev-parse --abbrev-ref HEAD) != "main" ]] ; then echo "\nYou need to be on the main branch to release.\n" && exit 1 ; fi
 	@# All our help options should be up-to-date
 	@COLUMNS=80 ./g 3 -h > cli-options.txt
 	@printf "\n== SANITY CHECK: GIT STATUS ==\n"
diff --git a/README-pypi.rst b/README-pypi.rst
index 124863c..63e7d4e 100644
--- a/README-pypi.rst
+++ b/README-pypi.rst
@@ -29,4 +29,4 @@ Features
 .. _Python Testing with Green: https://www.udemy.com/python-testing-with-green/?couponCode=GREEN_ANGEL
 .. _coverage: http://nedbatchelder.com/code/coverage/
 .. _PyPy: http://pypy.org
-.. _changelog: https://github.com/CleanCut/green/blob/master/CHANGELOG.md
+.. _changelog: https://github.com/CleanCut/green/blob/main/CHANGELOG.md
diff --git a/README.md b/README.md
index 7a4a0ad..b5178c0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 [![Version](https://img.shields.io/pypi/v/green.svg?style=flat)](https://pypi.python.org/pypi/green)
 [![CI Status](https://github.com/CleanCut/green/workflows/CI/badge.svg)](https://github.com/CleanCut/green/actions)
-[![Coverage Status](https://img.shields.io/coveralls/CleanCut/green.svg?style=flat)](https://coveralls.io/r/CleanCut/green?branch=master)
+[![Coverage Status](https://img.shields.io/coveralls/CleanCut/green.svg?style=flat)](https://coveralls.io/r/CleanCut/green?branch=main)
 
 # Green -- A clean, colorful, fast python test runner.
 
@@ -19,7 +19,7 @@ Features
 - **Modern** - Supports Python 3.5+. Additionally, [PyPy](http://pypy.org) is supported on a best-effort basis.
 - **Portable** - macOS, Linux, and BSDs are fully supported.  Windows is supported on a best-effort basis.
 - **Living** - This project grows and changes.  See the
-  [changelog](https://github.com/CleanCut/green/blob/master/CHANGELOG.md)
+  [changelog](https://github.com/CleanCut/green/blob/main/CHANGELOG.md)
 
 Community
 ---------
@@ -39,14 +39,14 @@ Training Course
 There is a training course available if you would like professional training:
 [Python Testing with Green](https://www.udemy.com/python-testing-with-green/?couponCode=GREEN_GITHUB).
 
-<a href="https://www.udemy.com/python-testing-with-green/?couponCode=GREEN_GITHUB" rel="Python Testing with Green"> ![Python Testing with Green](https://raw.githubusercontent.com/CleanCut/green/master/img/GreenCourseImagePromoStripe.png)</a>
+<a href="https://www.udemy.com/python-testing-with-green/?couponCode=GREEN_GITHUB" rel="Python Testing with Green"> ![Python Testing with Green](https://raw.githubusercontent.com/CleanCut/green/main/img/GreenCourseImagePromoStripe.png)</a>
 
 Screenshots
 -----------
 
 #### Top: With Green!  Bottom: Without Green :-(
 
-![Python Unit Test Output](https://raw.githubusercontent.com/CleanCut/green/master/img/screenshot.png)
+![Python Unit Test Output](https://raw.githubusercontent.com/CleanCut/green/main/img/screenshot.png)
 
 
 Quick Start
@@ -83,7 +83,7 @@ green green
 ```
 
 For more help, see the [complete command-line
-options](https://github.com/CleanCut/green/blob/master/cli-options.txt) or run
+options](https://github.com/CleanCut/green/blob/main/cli-options.txt) or run
 `green --help`.
 
 Config Files
@@ -97,12 +97,12 @@ in the resolution chain overwriting earlier settings (last setting wins).
 3) `setup.cfg` in the current working directory of test run
 4) `.green` in the current working directory of the test run
 5) A config file specified by the command-line argument `--config FILE`
-6) [Command-line arguments](https://github.com/CleanCut/green/blob/master/cli-options.txt)
+6) [Command-line arguments](https://github.com/CleanCut/green/blob/main/cli-options.txt)
 
 Any arguments specified in more than one place will be overwritten by the
 value of the LAST place the setting is seen.  So, for example, if a setting
 is turned on in `~/.green` and turned off by a
-[command-line argument](https://github.com/CleanCut/green/blob/master/cli-options.txt),
+[command-line argument](https://github.com/CleanCut/green/blob/main/cli-options.txt),
 then the setting will be turned off.
 
 Config file format syntax is `option = value` on separate lines.  `option` is
@@ -235,7 +235,7 @@ This tutorial covers:
 - DocTests
 
 For more in-depth online training please check out
-[Python Testing with Green](https://github.com/CleanCut/green/blob/master/PythonTestingWithGreen.md):
+[Python Testing with Green](https://github.com/CleanCut/green/blob/main/PythonTestingWithGreen.md):
 
 - Layout your test packages and modules correctly
 - Organize your tests effectively
diff --git a/green/VERSION b/green/VERSION
index 15a2799..1809198 100644
--- a/green/VERSION
+++ b/green/VERSION
@@ -1,1 +1,1 @@
-3.3.0
+3.4.0
diff --git a/green/djangorunner.py b/green/djangorunner.py
index c6141cf..9c5a486 100644
--- a/green/djangorunner.py
+++ b/green/djangorunner.py
@@ -133,6 +133,5 @@ try:
             self.teardown_test_environment()
             return self.suite_result(suite, result)
 
-
 except ImportError:  # pragma: no cover
     DjangoRunner = django_missing
diff --git a/green/result.py b/green/result.py
index 8980f58..bd90de2 100644
--- a/green/result.py
+++ b/green/result.py
@@ -126,20 +126,27 @@ class ProtoTest:
         )
 
     def getDescription(self, verbose):
+        # Classes or module teardown errors
         if self.is_class_or_module_teardown_error:
             return self.name
-        if verbose == 2:
-            if self.is_doctest:
+        # Doctests
+        if self.is_doctest:
+            if verbose == 2:
                 return self.name
-            return self.method_name + self.subtest_part
-        elif verbose > 2:
-            if self.is_doctest:
+            elif verbose > 2:
                 return self.name + " -> " + self.filename + ":" + str(self.lineno)
-            return (self.docstr_part + self.subtest_part) or (
-                self.method_name + self.subtest_part
-            )
-        else:
             return ""
+        # Regular tests
+        if verbose == 2:
+            return self.method_name + self.subtest_part
+        elif verbose == 3:
+            return (self.docstr_part + self.subtest_part) or self.method_name
+        elif verbose > 3:
+            if self.docstr_part + self.subtest_part:
+                return self.method_name + ": " + self.docstr_part + self.subtest_part
+            else:
+                return self.method_name
+        return ""
 
 
 class ProtoError:


Test patch:
diff --git a/green/test/test_result.py b/green/test/test_result.py
index fa4f1be..6d896a2 100644
--- a/green/test/test_result.py
+++ b/green/test/test_result.py
@@ -274,18 +274,20 @@ class TestProtoTest(unittest.TestCase):
         self.assertEqual(t.getDescription(1), "")
         self.assertEqual(t.getDescription(2), "test_stuff")
         self.assertEqual(t.getDescription(3), "apple")
-        self.assertEqual(t.getDescription(4), "apple")
+        self.assertEqual(t.getDescription(4), "test_stuff: apple")
+        self.assertEqual(t.getDescription(5), "test_stuff: apple")
 
         # Without a docstring
         class Vegetable(unittest.TestCase):
-            def test_stuff(self):
+            def test_vegetable(self):
                 pass
 
-        t = proto_test(Vegetable("test_stuff"))
+        t = proto_test(Vegetable("test_vegetable"))
         self.assertEqual(t.getDescription(1), "")
-        self.assertEqual(t.getDescription(2), "test_stuff")
-        self.assertEqual(t.getDescription(3), "test_stuff")
-        self.assertEqual(t.getDescription(4), "test_stuff")
+        self.assertEqual(t.getDescription(2), "test_vegetable")
+        self.assertEqual(t.getDescription(3), "test_vegetable")
+        self.assertEqual(t.getDescription(4), "test_vegetable")
+        self.assertEqual(t.getDescription(5), "test_vegetable")
 
     def test_newlineDocstring(self):
         """
@@ -336,6 +338,9 @@ class TestProtoTest(unittest.TestCase):
         dt = parser.get_doctest(test, {"f": f}, "doctest.name", "somefile.py", 20)
         dt.__module__ = "somefile"
         p = proto_test(doctest.DocTestCase(dt))
+        # no description
+        self.assertEqual(p.getDescription(0), "")
+        self.assertEqual(p.getDescription(1), "")
         # short description
         self.assertEqual(p.getDescription(2), "doctest.name")
         # long description
@@ -343,6 +348,11 @@ class TestProtoTest(unittest.TestCase):
         self.assertIn("doctest.name", description)
         self.assertIn("somefile.py", description)
         self.assertIn("20", description)
+        # very long == long
+        description = p.getDescription(4)
+        self.assertIn("doctest.name", description)
+        self.assertIn("somefile.py", description)
+        self.assertIn("20", description)
         # dotted name
         self.assertEqual(p.dotted_name, "doctest.name")