3

まず第一に、StackOverflowコミュニティへの継続的な貢献に感謝したいと思います。私は何年もの間StackOverflowのメンバーであり、オンラインの他のどのソースよりもあなたの入力に依存するようになりました。できる限り参加してメンバーの質問に答えようとしていますが、たまに行き詰まって助けを必要としていることに気づきます。

そういえば、私は異常なコードの問題を抱えています。WPF / Windowsフォームアプリケーションからだけでなく、単体テストコード内からも呼び出すことができる必要があるC#でAPIライブラリを作成しています。

問題は、APIがWPF / Windowsフォームアプリケーション内から呼び出されたときにライブラリの各メソッドが適切に実行されたかどうかを、他のメタデータとオプションでリターンタイプとともに(Excelで)レポートできる必要があることです。

単体テスト内でコードが消費される場合、レポートについてはあまり気にしませんが、API呼び出しが適切に実行されたかどうかに関するアサーションを生成できる必要があります。

たとえば、単体テストにTest Initialize一部がある場合、API呼び出しの1つは、使用するテストメソッドのドメインユーザーを作成することです。別のユーザーがドメイングループを作成して、ユーザーが適切なグループメンバーシップを持つようにすることもできます。

WPF / WinFormsからのAPIの使用に対応するために、API内のすべての関数を書き直して型を返し、すべてのAPI呼び出しが実行されたときに、CSVファイルに書き込むことができるようにOperationStepなることを期待しています。IEnumerable<OperationStep>

だから問題は、私がこれまでにやったことを達成するためのより簡単な方法があるのか​​ということです。APIライブラリが何百もの同様のメソッドで構成されていることを考えると、レポートはコーディングに非常に面倒で時間がかかります。サンプルを以下に説明します。

OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);

DomainContextは、ドメインコントローラに接続してユーザー、グループを作成し、ユーザーをグループに関連付ける機能を持つシングルトンオブジェクトです。

2番目と3番目のメソッド呼び出しはどちらも最初のメソッド呼び出しを必要とするため、以下で説明するようにオブジェクトpublic T Context内にある必要があることに注意してください。OperationResult

オブジェクトは、を除いてインターフェイスにOperationStep継承される次のプロパティで構成されます。IOperationpublic T Context

public class OperationStep<T> : IOperation
{
    /// <summary>
    /// Denotes the Logical Name of the current operation
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup 
    /// </summary>
    public OperationStage Stage { get; set; }

    /// <summary>
    /// Denotes whether the test step completed properly or failed.
    /// </summary>
    public OperationResult Result { get; set; }

    /// <summary>
    /// Denotes the return type of the test method.
    /// </summary>
    public T Context { get; set; }

    /// <summary>
    /// Denotes any other relevant information about the test step
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// If the test step result is failed, this should have the stack trace and the error message.
    /// </summary>
    public string Error { get; set; }
}

メソッド呼び出し自体は少し肥大化して退屈ですが、ここにサンプルがあります。

public class DomainContext
{
    private static volatile DomainContext currentContext;
    private static object synchronizationToken = new object();

    /// <summary>
    /// default ctor.
    /// </summary>
    private DomainContext() { }

    /// <summary>
    /// Retrieves the Current DomainContext instance.
    /// </summary>
    public static DomainContext Current
    {
        get
        {
            if (currentContext == null)
            {
                lock (synchronizationToken)
                {
                    if (currentContext == null)
                    {
                        currentContext = new DomainContext();
                    }
                }
            }
            return currentContext;
        }
    }

    /// <summary>
    /// Establishes a connection to the domain.
    /// </summary>
    /// <param name="domainInfo"></param>
    /// <returns></returns>
    public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
    {
        OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
        result.Name = "Establish Connection to Active Directory";
        result.Result = OperationResult.Success;
        result.Stage = OperationStage.Setup;
        result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);

        try
        {
            ContextType contextType = this.GetContextType(domainInfo.DomainType);
            PrincipalContext principalContext;

            try
            {
                principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
            }
            catch
            {
                throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
            }

            if (principalContext != null)
            {
                bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);

                if (!authenticationResult)
                {
                    throw new Exception("Unable to authenticate domain admin user to Active Directory.");
                }

                result.Context = principalContext;
                result.Result = OperationResult.Success;
            }
        }
        catch(Exception ex)
        {
            result.Error = ex.Message;
            result.Result = OperationResult.Failure;
        }

        return result;
    }
}

すべてのメソッド呼び出しが理論的に実行されたらIEnumerable<IOperation>、winフォームの場合はcsvファイル(MS Excelで表示)に書き込むことができます。ユニットテストの場合は、追加情報を省略できます。無視します(連続して実行されるメソッドとT Contextプロパティを除く)。

4

1 に答える 1

1

私があなたを正しく理解していればOperationStep、ここにあるのはすべてログ記録のためだけです。それでは、単純な .NET ロギングを有効にしてみませんか? 必要な情報を都合のよい場所に記録します。TraceSourcewithを使用しDelimetedTraceListenerて .csv ファイルに書き込むことができます。それ以上。ロギング ロジックをStrategyクラスに移動し、単体テストでそのロギング メソッドをオーバーライドして、ロギングの代わりに Assert メソッドを呼び出すことができます。

于 2013-03-27T06:53:50.733 に答える