c# - 进入/退出方法时如何增加/减少缩进?

标签 c# testing logging log4net data-driven-tests

TL;DR - 跳转到最后一段

背景

我正在执行一些数据驱动测试,并将日志文件用作测试输出之一。它的工作原理是这样的-

  • 读取文件夹中的第一个文件
    • 处理第一行并转换为测试
    • 运行测试
      • 执行验证 1
      • ...
    • ...
  • 阅读下一个文件

我的日志文件反射(reflect)了这一点:

INFO - Start RunAllFilesInFolder  
INFO - File1:
INFO -      Some info
INFO -      Executing Test 1  
INFO -          Validation A result
INFO -          ...
INFO -      ...  
INFO - File2:  
...

目前我这样使用/调用 Log 4 net-

static class LogHelper
{
    internal static readonly log4net.ILog Log = log4net.LogManager.GetLogger
            (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}

// another file
using static Some.Namespace.LogHelper;
class SomeClass
{
     Log.Info($"\t\tExecuting {t.Number}-{t.Name}");
}

缩进 = "\t"、"\t\t"或 "\t\t\t"取决于测试所在的级别。


有没有一种方法可以重构对 LogHelper.Log 的调用,以便它考虑静态“缩进”,当我进入不同的测试级别时可以增加/减少,而无需在每次调用中明确指定缩进?

即 能够在适用的情况下调用类似

Log.Indent.Increase();

或者

Log.Indent.Decrease();

并将上面的调用简单地替换为 -

Log.Info($"Executing {t.Number}-{t.Name}");

最佳答案

您可以使用 stack trace长度,通过计算新行的数量:

int someSensibleMinimum = 3; //something that works for you
int count = Environment.StackTrace.Count(a => a=='\n');
var indent = new string('\t', Math.Max(0, count - someSensibleMinimum));

请注意,在 Release 中它的行为可能会有所不同:

However, the StackTrace property might not report as many method calls as expected due to code transformations that occur during optimization.

或者,您可以使用这种方法(伪代码)自动计算长度:

int count = Environment.StackTrace.Count(a => a=='\n');
Look for stack length in dictionary<int,string> (length to indent string)
If found use it.
If not found, find the largest entry in dictionary where key < count
add new entry to dictionary one tab char longer

在代码中:

public sealed class IndentTracker
{
    private readonly ThreadLocal<Dictionary<int, string>> _dictionaryLocal =
        new ThreadLocal<Dictionary<int, string>>(() => new Dictionary<int, string>());

    public string GetIndent()
    {
        Dictionary<int, string> dictionary = _dictionaryLocal.Value;

        int count = Environment.StackTrace.Count(a => a == '\n');

        if (!dictionary.Any())
        {
            string initialIndent = string.Empty;
            dictionary.Add(count, initialIndent);
            return initialIndent;
        }

        string indent;
        if (dictionary.TryGetValue(count, out indent))
            return indent;

        string last = dictionary.OrderByDescending(k => k.Key).First(k => k.Key < count).Value;
        string newIndent = last + '\t';
        dictionary.Add(count, newIndent);
        return newIndent;
    }
}

这在按递增深度顺序登录时有效。例如,如果您在堆栈深度 10 然后 5 记录(之前没有在堆栈深度 5 然后 10 记录),它将失败。

关于c# - 进入/退出方法时如何增加/减少缩进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36195744/

相关文章:

Tomcat Catalina 错误日志未显示在控制台上

c# - 多个更新面板的问题

c# - 属性路由返回404

javascript - 在源文件之前在 Jasmine on Rails 3.1 插件上加载 jQuery

java - 有没有办法在不抛出异常的情况下转储堆栈跟踪?

Python日志记录: debug messages logged to stderr even though handler level is INFO

c# - 偶尔(OAuthException - #200)(#200)用户必须接受 TOS

c# - 无法将类型 'Microsoft.Azure.Documents.Document' 隐式转换为 'System.Web.Http.IHttpActionResult' 。

android - 在 Android 中测试 Main/Launcher Activity

android - 关于多个dex文件定义Lcom/google/gson/JsonSerializer