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

时间:2016-03-24 08:18:00

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

TL; DR - 跳到最后一段

背景

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

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

我的日志文件反映了这一点:

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}");
}

其中indent =“\ t”,“\ t \ t”或“\ t \ t \ t”取决于测试所在的级别。

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

即。 能够在适用的地方打电话,如

Log.Indent.Increase();

或者

Log.Indent.Decrease();

将上述调用替换为仅使用 -

进行日志记录
Log.Info($"Executing {t.Number}-{t.Name}");

1 个答案:

答案 0 :(得分:1)

您可以使用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中,它可能表现不同:

  

但是,由于优化期间发生的代码转换,StackTrace属性可能无法报告与预期一样多的方法调用。

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

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),则会失败。