Действительно ли это возможно в C#?

Да, даже если Вы - единственное управление исходным кодом человека, необходимость. Конечно, Вы не будете использовать его для управления, кто работает, на которых файлах, но наличии способности к роли, назад если Вы делаете большую ошибку в своем коде, действительно легкая задача.

8
задан whatupdave 8 December 2009 в 23:05
поделиться

5 ответов

Вы можете получить код, если это отладочная сборка, используя некоторые классы диагностики. Учитывая, что это для модульных тестов, DEBUG, вероятно, разумен.

public static void ShouldBe<T>(this T actual, T expected)

{

var frame = new StackTrace(true).GetFrame(1);
var fileName = frame.GetFileName();
var lineNumber = frame.GetFileLineNumber() - 1;

string code = File.ReadLines(fileName).ElementAt(lineNumber).Trim();

Debug.Assert(actual.Equals(expected), code);

}

Для вашего примера code = "steve.BrainsConsumed.ShouldBe (0);"

Очевидно, вам следует добавить некоторую ошибку проверяя этот код, и вы, вероятно, могли бы сделать это быстрее, не читая все строки в файле.

3
ответ дан 5 December 2019 в 21:19
поделиться

Лучшее, что я могу сделать, это:

steve.Property(p => p.BrainsConsumed).ShouldBe(0);

или:

steve.ShouldBe(p => p.BrainsConsumed, 0);

или:

Assert.AreEqual(() => steve.BrainsConsumed, 0);

Re:

Бонусными баллами будет переменная экземпляра

. При использовании Expression > (или просто Expression > ) вы можете довольно легко получить имя и значение свойства. Я' Я сделаю пример для середины - обратите внимание, что для первого требуется дополнительный тип для DSL, но ничего тяжелого:

public static class Test
{
    public static void AssertEqual<TSource, TValue>(
        this TSource source,
        Expression<Func<TSource, TValue>> selector,
        TValue expected)
        where TSource : class
    {
        TValue value = selector.Compile()(source);
        string paramName = selector.Parameters[0].Name;

        System.Diagnostics.Debug.Assert(
            EqualityComparer<TValue>.Default.Equals(value, expected),
            typeof(TSource) + " " + paramName + ": " +
                value + " doesn't match expected " + expected);
    }
}

Или чуть лучше сообщение:

public class Zombie
{
    public int BrainsConsumed { get; set; }
    static void Main() {
        Zombie steve = new Zombie { BrainsConsumed = 2 };
        Test.ShouldBeEqual(() => steve.BrainsConsumed, 0);
    }

}
public static class Test
{
    static string GetName(Expression expr)
    {
        if (expr.NodeType == ExpressionType.MemberAccess)
        {
            var me = (MemberExpression)expr;
            string name = me.Member.Name, subExpr = GetName(me.Expression);
            return string.IsNullOrEmpty(subExpr)
                ? name : (subExpr + "." + name);
        }
        return "";
    }
    public static void ShouldBeEqual<TValue>(
        Expression<Func<TValue>> selector,
        TValue expected)
    {
        TValue value = selector.Compile()();

        string name = GetName(selector.Body);

        System.Diagnostics.Debug.Assert(
            EqualityComparer<TValue>.Default.Equals(value, expected),
            typeof(TValue) + " " + name + ": " +
                value + " doesn't match expected " + expected);
    }
}
3
ответ дан 5 December 2019 в 21:19
поделиться

Нет, я не думаю, что сможете.

Предположим, что BrainsConsumed - целое число (что выглядит вероятным). В этом случае параметр передается по значению - все, что вы получаете, - это копия тестируемого целого числа. У него нет имени, кроме имени в локальной области (фактического).

Этот аналогичный вопрос может прояснить:

Поиск имени переменной, переданного функции

1
ответ дан 5 December 2019 в 21:19
поделиться

Это позволит вам протестировать его, но не даст вам имя метода.

У вас может быть это расширение:

public static void ShouldBe<T>(this Func<T> func, T expected)
{
    Assert.AreEqual(func(), expected);
}

Со следующим использованием:

((Func<int>)Program.TestMethod).ShouldBe(2);
0
ответ дан 5 December 2019 в 21:19
поделиться

К сожалению, в этой позиции вы не сможете получить имя свойства на этом этапе. Проблема в том, что вы передаете значение поля BrainsConsumed, и в этот момент просто нет обратной ссылки на Zombie (что касается вашего метода, это int, и он не может сработать, откуда изначально пришел int from).

Лучшее, что я мог придумать для вас, - это то, что Environment.StackTrace будет содержать соответствующую информацию, так как вы вызвали steve.BrainsConsumed на 1 шаг вверх по стеку (рекомендуется только в том случае, если вы пытаюсь понять, что не удалось в ваших модульных тестах - не если они действительно проходят по стеку в обычном потоке программы).

0
ответ дан 5 December 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: