diff --git a/samples/BenchmarkDotNet.Samples/IntroRenameTest.cs b/samples/BenchmarkDotNet.Samples/IntroRenameTest.cs
new file mode 100644
index 0000000000..525e16f1dc
--- /dev/null
+++ b/samples/BenchmarkDotNet.Samples/IntroRenameTest.cs
@@ -0,0 +1,22 @@
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace BenchmarkDotNet.Samples
+{
+    [BenchmarkDescription("Used to be 'IntroRenameTest', now is 'My Renamed Test'")]
+    public class IntroRenameTest
+    {
+        // And define a method with the Benchmark attribute
+        [Benchmark]
+        public void Sleep() => Thread.Sleep(10);
+
+        // You can write a description for your method.
+        [Benchmark(Description = "Thread.Sleep(10)")]
+        public void SleepWithDescription() => Thread.Sleep(10);
+    }
+}
diff --git a/src/BenchmarkDotNet.Annotations/Attributes/BenchmarkDescriptionAttribute.cs b/src/BenchmarkDotNet.Annotations/Attributes/BenchmarkDescriptionAttribute.cs
new file mode 100644
index 0000000000..1b3aad7f07
--- /dev/null
+++ b/src/BenchmarkDotNet.Annotations/Attributes/BenchmarkDescriptionAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BenchmarkDotNet.Attributes
+{
+    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
+    public class BenchmarkDescriptionAttribute : Attribute
+    {
+        public BenchmarkDescriptionAttribute(){        }
+        public BenchmarkDescriptionAttribute(string description)
+            => Description = description;
+
+        public string Description { get; set; }
+    }
+}
diff --git a/src/BenchmarkDotNet/Columns/TargetMethodColumn.cs b/src/BenchmarkDotNet/Columns/TargetMethodColumn.cs
index f6bcb3ef31..d0b9da6da7 100644
--- a/src/BenchmarkDotNet/Columns/TargetMethodColumn.cs
+++ b/src/BenchmarkDotNet/Columns/TargetMethodColumn.cs
@@ -8,7 +8,7 @@ namespace BenchmarkDotNet.Columns
     public class TargetMethodColumn : IColumn
     {
         public static readonly IColumn Namespace = new TargetMethodColumn(Column.Namespace, benchmark => benchmark.Descriptor.Type.Namespace);
-        public static readonly IColumn Type = new TargetMethodColumn(Column.Type, benchmark => benchmark.Descriptor.Type.GetDisplayName());
+        public static readonly IColumn Type = new TargetMethodColumn(Column.Type, benchmark => benchmark.Descriptor.TypeInfo);
         public static readonly IColumn Method = new TargetMethodColumn(Column.Method, benchmark => benchmark.Descriptor.WorkloadMethodDisplayInfo, true);
 
         private readonly Func<BenchmarkCase, string> valueProvider;
diff --git a/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs b/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs
index cf1f71a166..5ce60cbe85 100644
--- a/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs
+++ b/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs
@@ -102,6 +102,10 @@ private static IEnumerable<string> GetNestedTypeNames(Type type, bool includeGen
         /// </summary>
         private static string GetDisplayName(this TypeInfo typeInfo)
         {
+            var customAttr = typeInfo.GetCustomAttribute<BenchmarkDescriptionAttribute>();
+            if (customAttr != null)
+                return customAttr.Description;
+
             if (!typeInfo.IsGenericType)
                 return typeInfo.Name;
 
diff --git a/src/BenchmarkDotNet/Running/BenchmarkConverter.cs b/src/BenchmarkDotNet/Running/BenchmarkConverter.cs
index dbe350b2c8..fa2523e1c8 100644
--- a/src/BenchmarkDotNet/Running/BenchmarkConverter.cs
+++ b/src/BenchmarkDotNet/Running/BenchmarkConverter.cs
@@ -127,6 +127,7 @@ private static IEnumerable<Descriptor> GetTargets(
                                                    GetTargetedMatchingMethod(methodInfo, iterationSetupMethods),
                                                    GetTargetedMatchingMethod(methodInfo, iterationCleanupMethods),
                                                    methodInfo.ResolveAttribute<BenchmarkAttribute>(),
+                                                   methodInfo.ResolveAttribute<BenchmarkDescriptionAttribute>(),
                                                    targetMethods,
                                                    config));
         }
@@ -155,10 +156,15 @@ private static Descriptor CreateDescriptor(
             MethodInfo iterationSetupMethod,
             MethodInfo iterationCleanupMethod,
             BenchmarkAttribute attr,
+            BenchmarkDescriptionAttribute? methodDescription,
             MethodInfo[] targetMethods,
             IConfig config)
         {
             var categoryDiscoverer = config.CategoryDiscoverer ?? DefaultCategoryDiscoverer.Instance;
+            if (attr?.Description != null && methodDescription?.Description != null)
+                throw new InvalidOperationException($"Benchmark {methodInfo.Name} has 2 descriptions from different attributes");
+            string description = attr?.Description;
+            description ??= methodDescription?.Description;
             var target = new Descriptor(
                 type,
                 methodInfo,
@@ -166,7 +172,7 @@ private static Descriptor CreateDescriptor(
                 globalCleanupMethod,
                 iterationSetupMethod,
                 iterationCleanupMethod,
-                attr.Description,
+                description,
                 baseline: attr.Baseline,
                 categories: categoryDiscoverer.GetCategories(methodInfo),
                 operationsPerInvoke: attr.OperationsPerInvoke,
diff --git a/src/BenchmarkDotNet/Running/Descriptor.cs b/src/BenchmarkDotNet/Running/Descriptor.cs
index a7fd0cd7ac..b72db09084 100644
--- a/src/BenchmarkDotNet/Running/Descriptor.cs
+++ b/src/BenchmarkDotNet/Running/Descriptor.cs
@@ -1,6 +1,8 @@
 using System;
+using System.Data;
 using System.Linq;
 using System.Reflection;
+using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Extensions;
 using BenchmarkDotNet.Helpers;
 using BenchmarkDotNet.Portability;
diff --git a/tests/BenchmarkDotNet.Tests/Exporters/JobBaseline_WithAttribute.cs b/tests/BenchmarkDotNet.Tests/Exporters/JobBaseline_WithAttribute.cs
new file mode 100644
index 0000000000..0b1aaaf959
--- /dev/null
+++ b/tests/BenchmarkDotNet.Tests/Exporters/JobBaseline_WithAttribute.cs
@@ -0,0 +1,14 @@
+using BenchmarkDotNet.Attributes;
+
+namespace BenchmarkDotNet.Tests.Exporters
+{
+    [RankColumn, LogicalGroupColumn, BaselineColumn]
+    [SimpleJob(id: "Job1"), SimpleJob(id: "Job2")]
+    [BenchmarkDescription(Description = "MyRenamedTestCase")]
+    public class JobBaseline_MethodsJobs_WithAttribute
+    {
+        [Benchmark] public void Base() { }
+        [Benchmark] public void Foo() { }
+        [Benchmark] public void Bar() { }
+    }
+}
diff --git a/tests/BenchmarkDotNet.Tests/Exporters/MarkdownExporterVerifyTests.cs b/tests/BenchmarkDotNet.Tests/Exporters/MarkdownExporterVerifyTests.cs
index 950f8498f8..23a7daf465 100644
--- a/tests/BenchmarkDotNet.Tests/Exporters/MarkdownExporterVerifyTests.cs
+++ b/tests/BenchmarkDotNet.Tests/Exporters/MarkdownExporterVerifyTests.cs
@@ -15,6 +15,8 @@
 using VerifyXunit;
 using Xunit;
 
+using static BenchmarkDotNet.Tests.Exporters.MarkdownExporterVerifyTests.BaselinesBenchmarks;
+
 namespace BenchmarkDotNet.Tests.Exporters
 {
     [Collection("VerifyTests")]
@@ -57,8 +59,31 @@ public Task GroupExporterTest(Type benchmarkType)
             var settings = VerifySettingsFactory.Create();
             settings.UseTextForParameters(benchmarkType.Name);
             return Verifier.Verify(logger.GetLog(), settings);
-        }
-
+        }
+
+        [Fact]
+        public Task GroupExporterMultipleTypesTest()
+        {
+            Type[] benchmarkTypes = new Type[] { typeof(JobBaseline_MethodsJobs_WithAttribute), typeof(JobBaseline_MethodsJobs) };
+            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
+            var logger = new AccumulationLogger();
+            logger.WriteLine("=== " + benchmarkTypes + " ===");
+
+            var exporter = MarkdownExporter.Mock;
+            var summary = MockFactory.CreateSummary(benchmarkTypes);
+            exporter.ExportToLog(summary, logger);
+
+            var validator = BaselineValidator.FailOnError;
+            var errors = validator.Validate(new ValidationParameters(summary.BenchmarksCases, summary.BenchmarksCases.First().Config)).ToList();
+            logger.WriteLine();
+            logger.WriteLine("Errors: " + errors.Count);
+            foreach (var error in errors)
+                logger.WriteLineError("* " + error.Message);
+
+            var settings = VerifySettingsFactory.Create();
+            return Verifier.Verify(logger.GetLog(), settings);
+        }
+
         public void Dispose() => Thread.CurrentThread.CurrentCulture = initCulture;
 
         [SuppressMessage("ReSharper", "InconsistentNaming")]
diff --git a/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterApprovalTests.GroupExporterTest.JobBaseline_RenameJob_MethodsJobs.approved.txt b/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterApprovalTests.GroupExporterTest.JobBaseline_RenameJob_MethodsJobs.approved.txt
new file mode 100644
index 0000000000..e8edaa833f
--- /dev/null
+++ b/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterApprovalTests.GroupExporterTest.JobBaseline_RenameJob_MethodsJobs.approved.txt
@@ -0,0 +1,20 @@
+=== JobBaseline_RenameJob_MethodsJobs ===
+
+BenchmarkDotNet=v0.10.x-mock, OS=Microsoft Windows NT 10.0.x.mock, VM=Hyper-V
+MockIntel Core i7-6700HQ CPU 2.60GHz (Max: 3.10GHz), 1 CPU, 8 logical and 4 physical cores
+Frequency=2531248 Hz, Resolution=395.0620 ns, Timer=TSC
+  [Host] : Clr 4.0.x.mock, 64mock RyuJIT-v4.6.x.mock CONFIGURATION
+  Job1   : extra output line
+  Job2   : extra output line
+
+
+ Method |  Job |     Mean |   Error |  StdDev | Rank | LogicalGroup | Baseline |
+------- |----- |---------:|--------:|--------:|-----:|------------- |--------- |
+   Base | Job1 | 102.0 ns | 6.09 ns | 1.58 ns |    1 |            * |       No |
+    Foo | Job1 | 202.0 ns | 6.09 ns | 1.58 ns |    2 |            * |       No |
+    Bar | Job1 | 302.0 ns | 6.09 ns | 1.58 ns |    3 |            * |       No |
+   Base | Job2 | 402.0 ns | 6.09 ns | 1.58 ns |    4 |            * |       No |
+    Foo | Job2 | 502.0 ns | 6.09 ns | 1.58 ns |    5 |            * |       No |
+    Bar | Job2 | 602.0 ns | 6.09 ns | 1.58 ns |    6 |            * |       No |
+
+Errors: 0
diff --git a/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterVerifyTests.GroupExporterMultipleTypesTest.verified.txt b/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterVerifyTests.GroupExporterMultipleTypesTest.verified.txt
new file mode 100644
index 0000000000..2e5dcab0a0
--- /dev/null
+++ b/tests/BenchmarkDotNet.Tests/Exporters/VerifiedFiles/MarkdownExporterVerifyTests.GroupExporterMultipleTypesTest.verified.txt
@@ -0,0 +1,31 @@
+=== System.Type[] ===
+
+BenchmarkDotNet v0.10.x-mock, Microsoft Windows NT 10.0.x.mock (Hyper-V)
+MockIntel Core i7-6700HQ CPU 2.60GHz (Max: 3.10GHz), 1 CPU, 8 logical and 4 physical cores
+Frequency: 2531248 Hz, Resolution: 395.0620 ns, Timer: TSC
+  [Host] : Clr 4.0.x.mock, 64mock RyuJIT-v4.6.x.mock CONFIGURATION
+  Job1   : extra output line
+  Job2   : extra output line
+
+
+                    Type | Method |  Job |       Mean |   Error |  StdDev | Ratio | RatioSD | Rank |                 LogicalGroup | Baseline |
+------------------------ |------- |----- |-----------:|--------:|--------:|------:|--------:|-----:|----------------------------- |--------- |
+       MyRenamedTestCase |   Base | Job1 |   102.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    1 |       MyRenamedTestCase.Base |       No |
+       MyRenamedTestCase |   Base | Job2 |   402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    2 |       MyRenamedTestCase.Base |       No |
+                         |        |      |            |         |         |       |         |      |                              |          |
+       MyRenamedTestCase |    Foo | Job1 |   202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    1 |        MyRenamedTestCase.Foo |       No |
+       MyRenamedTestCase |    Foo | Job2 |   502.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    2 |        MyRenamedTestCase.Foo |       No |
+                         |        |      |            |         |         |       |         |      |                              |          |
+       MyRenamedTestCase |    Bar | Job1 |   302.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    1 |        MyRenamedTestCase.Bar |       No |
+       MyRenamedTestCase |    Bar | Job2 |   602.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |    2 |        MyRenamedTestCase.Bar |       No |
+                         |        |      |            |         |         |       |         |      |                              |          |
+ JobBaseline_MethodsJobs |   Base | Job1 |   702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |    1 | JobBaseline_MethodsJobs.Base |      Yes |
+ JobBaseline_MethodsJobs |   Base | Job2 | 1,002.0 ns | 6.09 ns | 1.58 ns |  1.43 |    0.00 |    2 | JobBaseline_MethodsJobs.Base |       No |
+                         |        |      |            |         |         |       |         |      |                              |          |
+ JobBaseline_MethodsJobs |    Foo | Job1 |   802.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |    1 |  JobBaseline_MethodsJobs.Foo |      Yes |
+ JobBaseline_MethodsJobs |    Foo | Job2 | 1,102.0 ns | 6.09 ns | 1.58 ns |  1.37 |    0.00 |    2 |  JobBaseline_MethodsJobs.Foo |       No |
+                         |        |      |            |         |         |       |         |      |                              |          |
+ JobBaseline_MethodsJobs |    Bar | Job1 |   902.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |    1 |  JobBaseline_MethodsJobs.Bar |      Yes |
+ JobBaseline_MethodsJobs |    Bar | Job2 | 1,202.0 ns | 6.09 ns | 1.58 ns |  1.33 |    0.00 |    2 |  JobBaseline_MethodsJobs.Bar |       No |
+
+Errors: 0
diff --git a/tests/BenchmarkDotNet.Tests/Mocks/MockFactory.cs b/tests/BenchmarkDotNet.Tests/Mocks/MockFactory.cs
index b51f978edf..159fb00cb0 100644
--- a/tests/BenchmarkDotNet.Tests/Mocks/MockFactory.cs
+++ b/tests/BenchmarkDotNet.Tests/Mocks/MockFactory.cs
@@ -16,22 +16,23 @@
 namespace BenchmarkDotNet.Tests.Mocks
 {
     public static class MockFactory
-    {
-        public static Summary CreateSummary(Type benchmarkType)
-        {
-            var runInfo = BenchmarkConverter.TypeToBenchmarks(benchmarkType);
-            return new Summary(
-                "MockSummary",
-                runInfo.BenchmarksCases.Select((benchmark, index) => CreateReport(benchmark, 5, (index + 1) * 100)).ToImmutableArray(),
-                new HostEnvironmentInfoBuilder().WithoutDotNetSdkVersion().Build(),
-                string.Empty,
-                string.Empty,
-                TimeSpan.FromMinutes(1),
-                TestCultureInfo.Instance,
-                ImmutableArray<ValidationError>.Empty,
-                ImmutableArray<IColumnHidingRule>.Empty);
-        }
-
+    {
+        public static Summary CreateSummary(Type benchmarkType) => CreateSummary(new Type[] { benchmarkType });
+        public static Summary CreateSummary(Type[] benchmarkTypes)
+        {
+            var runInfos = benchmarkTypes.Select(benchmarkType => BenchmarkConverter.TypeToBenchmarks(benchmarkType));
+            return new Summary(
+                "MockSummary",
+                runInfos.SelectMany(runInfo => runInfo.BenchmarksCases).Select((benchmark, index) => CreateReport(benchmark, 5, (index + 1) * 100)).ToImmutableArray(),
+                new HostEnvironmentInfoBuilder().WithoutDotNetSdkVersion().Build(),
+                string.Empty,
+                string.Empty,
+                TimeSpan.FromMinutes(1),
+                TestCultureInfo.Instance,
+                ImmutableArray<ValidationError>.Empty,
+                ImmutableArray<IColumnHidingRule>.Empty);
+        }
+
         public static Summary CreateSummary(IConfig config) => new Summary(
                 "MockSummary",
                 CreateReports(config),
diff --git a/tests/BenchmarkDotNet.Tests/Running/BenchmarkConverterTests.cs b/tests/BenchmarkDotNet.Tests/Running/BenchmarkConverterTests.cs
index 4eb72b5d59..5875b48629 100644
--- a/tests/BenchmarkDotNet.Tests/Running/BenchmarkConverterTests.cs
+++ b/tests/BenchmarkDotNet.Tests/Running/BenchmarkConverterTests.cs
@@ -212,6 +212,29 @@ public void MethodDeclarationOrderIsPreserved()
                 Assert.Equal(nameof(BAC.C), info.BenchmarksCases[2].Descriptor.WorkloadMethod.Name);
             }
         }
+        [Fact]
+        public void OnlyOneOfAttributeDescriptionIsUsed()
+        {
+            Assert.Throws<InvalidOperationException>(() => BenchmarkConverter.TypeToBenchmarks(typeof(BothAttributeDescriptionTests)));
+        }
+        [Fact]
+        public void DescriptorDescriptionNameOverride()
+        {
+            var description = BenchmarkConverter.TypeToBenchmarks(typeof(MethodDescriptionOverrideTests));
+
+            Assert.Equal("VoidTest", description.BenchmarksCases[0].Descriptor.WorkloadMethodDisplayInfo);
+            Assert.Equal("\'from Benchmark\'", description.BenchmarksCases[1].Descriptor.WorkloadMethodDisplayInfo);
+            Assert.Equal("OverrideFromAttribute", description.BenchmarksCases[2].Descriptor.WorkloadMethodDisplayInfo);
+        }
+        [Fact]
+        public void ClassDescriptorDescriptionNameOverride()
+        {
+            var description = BenchmarkConverter.TypeToBenchmarks(typeof(ClassDescriptionOverrideTests));
+
+            Assert.Equal("FromClassDescription", description.BenchmarksCases[0].Descriptor.WorkloadMethodDisplayInfo);
+            Assert.Equal("\'from Benchmark\'", description.BenchmarksCases[1].Descriptor.WorkloadMethodDisplayInfo);
+            Assert.Equal("OverrideFromAttribute", description.BenchmarksCases[2].Descriptor.WorkloadMethodDisplayInfo);
+        }
 
         public class BAC
         {
@@ -278,5 +301,36 @@ public class PrivateIterationCleanup
             [IterationCleanup] private void X() { }
             [Benchmark] public void A() { }
         }
+        public class BothAttributeDescriptionTests
+        {
+            [Benchmark(Description = "BenchmarkAttributeDescription")]
+            [BenchmarkDescription("BenchmarkDescriptionAttributeDescription")]
+            public void BothDescriptionsUsed() { }
+        }
+        public class MethodDescriptionOverrideTests
+        {
+            [Benchmark]
+            public void VoidTest() { }
+
+            [Benchmark(Description = "from Benchmark")]
+            public void BenchmarkAttributeOverride() {}
+
+            [Benchmark]
+            [BenchmarkDescription("OverrideFromAttribute")]
+            public void BenchmarkDescriptionAttributeOverride() { }
+        }
+        [BenchmarkDescription("FromClassDescription")]
+        public class ClassDescriptionOverrideTests
+        {
+            [Benchmark]
+            public void VoidTest() { }
+
+            [Benchmark(Description = "from Benchmark")]
+            public void ClassBenchmarkAttributeOverride() { }
+
+            [Benchmark]
+            [BenchmarkDescription("OverrideFromAttribute")]
+            public void ClassBenchmarkDescriptionAttributeOverride() { }
+        }
     }
 }