12

問題

VS2010 と TFS2010 は、いわゆるコード化された UI テストの作成をサポートしています。私が見つけたすべてのデモは、コード化された UI テストが開始されるか、絶対パスを使用して EXE が開始されたときに、バックグラウンドで既に実行されている WPF アプリケーションから開始します。

ただし、単体テスト コードからテスト対象の WPF アプリケーションを開始したいと考えています。そうすれば、ビルド サーバーとピアの作業コピーでも機能します。

どうすればそれを達成できますか?

これまでの私の発見

a) この投稿では、XAML ウィンドウを開始する方法を示します。しかし、それは私が望むものではありません。XAML リソースが含まれており、コード ビハインド ファイルにアプリケーション ロジックがあるため、App.xaml を開始します。

b)この投稿の 2 番目のスクリーンショットは、

ApplicationUnterTest calculatorWindow = ApplicationUnderTest.Launch(...);

これは概念的には私が探しているものとほぼ同じですが、この例でも実行可能ファイルの絶対パスを使用しています。

c)「プログラムでWPFを開始する」というGoogle検索も役に立ちませんでした。

4

5 に答える 5

5
MyProject.App myApp = new MyProject.App();
myApp.InitializeComponent();
myApp.Run();
于 2010-03-04T12:43:09.273 に答える
4

私はVS2008で同様のことを行っており、UI Spyを使用して手動でテストを作成し、ボタンのクリックをトリガーして画面上の値を確認するためのコントロールといくつかのヘルパーメソッド(表示されていません)を識別します。Processオブジェクトを使用して、TestInitializeメソッドでテストしているアプリケーションを起動し、TestCleanupメソッドでプロセスを閉じます。CleanUpでプロセスが完全に終了したことを確認する方法はいくつかあります。絶対パスの問題については、プログラムで現在のパスを検索し、アプリケーションの実行可能ファイルを追加するだけです。アプリケーションの起動にかかる時間がわからないので、メインウィンドウにAutomationIdを配置し、それを「UserApplicationWindow」に設定して、それが表示されるのを待ちます。もちろん、他に待つことができるものがあるかもしれません。 。ついに、

[TestClass]
public class MyTestClass
{
    private Process _userAppProcess;
    private AutomationElement _userApplicationElement ;

    /// <summary>
    /// Gets the current directory where the executables are located.  
    /// </summary>
    /// <returns>The current directory of the executables.</returns>
    private static String GetCurrentDirectory()
    {
        return Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).AbsolutePath).Replace("%20", " ");
    }

    [TestInitialize]
    public void SetUp()
    {
        Thread appThread = new Thread(delegate()
        {
            _userAppProcess = new Process();
            _userAppProcess.StartInfo.FileName =GetCurrentDirectory() + "\\UserApplication.exe";
            _userAppProcess.StartInfo.WorkingDirectory = DirectoryUtils.GetCurrentDirectory();
            _userAppProcess.StartInfo.UseShellExecute = false;
            _userAppProcess.Start();
        });
        appThread.SetApartmentState(ApartmentState.STA);
        appThread.Start();

        WaitForApplication();
    }

    private void WaitForApplication()
    {
        AutomationElement aeDesktop = AutomationElement.RootElement;
        if (aeDesktop == null)
        {
            throw new Exception("Unable to get Desktop");
        }

        _userApplicationElement = null;
        do
        {
            _userApplicationElement = aeDesktop.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.AutomationIdProperty, "UserApplicationWindow"));
            Thread.Sleep(200);
        } while ( (_userApplicationElement == null || _userApplicationElement.Current.IsOffscreen) );

    }

    [TestCleanup]
    public void CleanUp()
    {
        try
        {
            // Tell the application's main window to close.
            WindowPattern window = _userApplicationElement.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern ;
            window.Close();
            if (!_userAppProcess.WaitForExit(3000))
            {
                // We waited 3 seconds for the User Application to close on its own.  
                // Send a close request again through the process class.
                _userAppProcess.CloseMainWindow();
            }

            // All done trying to close the window, terminate the process
            _userAppProcess.Close();
            _userAppProcess = null; 
        }
        catch (Exception ex)
        {
            // I know this is bad, but catching the world is better than letting it fail.
        }
    }
}
于 2010-03-08T23:49:25.360 に答える
1

Microsoft Test Manager で自動テストを記録するときに自動的に作成されるApplicationUnderTest.Launch(...) ( MSDN ) を使用することになりました。

于 2010-03-14T14:33:05.590 に答える
0

Caliburn microのユニットテストに少し成功した、私が一緒にハッキングしたものは次のとおりです。

[TestFixture]
public class when_running_bootstrapper
{
    [Test]
    public void it_should_request_its_view_model()
    {
        TestFactory.PerformRun(b =>
            CollectionAssert.Contains(b.Requested, typeof(SampleViewModel).FullName));
    }

    [Test]
    public void it_should_request_a_window_manager_on_dotnet()
    {
        TestFactory.PerformRun(b => 
            CollectionAssert.Contains(b.Requested, typeof(IWindowManager).FullName));
    }

    [Test]
    public void it_should_release_the_window_manager_once()
    {
        TestFactory.PerformRun(b =>
            Assert.That(b.ReleasesFor<IWindowManager>(), Is.EqualTo(1)));
    }

    [Test]
    public void it_should_release_the_root_view_model_once()
    {
        TestFactory.PerformRun(b =>
            Assert.That(b.ReleasesFor<SampleViewModel>(), Is.EqualTo(1)));
    }
}

static class TestFactory
{
    public static void PerformRun(Action<TestBootStrapper> testLogic)
    {
        var stackTrace = new StackTrace();
        var name = stackTrace.GetFrames().First(x => x.GetMethod().Name.StartsWith("it_should")).GetMethod().Name;
        var tmpDomain = AppDomain.CreateDomain(name,
            AppDomain.CurrentDomain.Evidence,
            AppDomain.CurrentDomain.BaseDirectory,
            AppDomain.CurrentDomain.RelativeSearchPath,
            AppDomain.CurrentDomain.ShadowCopyFiles);
        var proxy = (Wrapper)tmpDomain.CreateInstanceAndUnwrap(typeof (TestFactory).Assembly.FullName, typeof (Wrapper).FullName);

        try
        {
            testLogic(proxy.Bootstrapper);
        }
        finally
        {
            AppDomain.Unload(tmpDomain);
        }
    }
}

[Serializable]
public class Wrapper
    : MarshalByRefObject
{
    TestBootStrapper _bootstrapper;

    public Wrapper()
    {
        var t = new Thread(() =>
            {
                var app = new Application();
                _bootstrapper = new TestBootStrapper(app);
                app.Run();
            });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        t.Join();
    }

    public TestBootStrapper Bootstrapper
    {
        get { return _bootstrapper; }
    }
}

[Serializable]
public class TestBootStrapper
    : Bootstrapper<SampleViewModel>
{
    [NonSerialized]
    readonly Application _application;

    [NonSerialized]
    readonly Dictionary<Type, object> _defaults = new Dictionary<Type, object>
        {
            { typeof(IWindowManager), new WindowManager() }
        };

    readonly Dictionary<string, uint> _releases = new Dictionary<string, uint>();
    readonly List<string> _requested = new List<string>();

    public TestBootStrapper(Application application)
    {
        _application = application;
    }

    protected override object GetInstance(Type service, string key)
    {
        _requested.Add(service.FullName);

        if (_defaults.ContainsKey(service))
            return _defaults[service];

        return new SampleViewModel();
    }

    protected override void ReleaseInstance(object instance)
    {
        var type = instance.GetType();
        var t = (type.GetInterfaces().FirstOrDefault() ?? type).FullName;

        if (!_releases.ContainsKey(t))
            _releases[t] = 1;
        else
            _releases[t] = _releases[t] + 1;
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        throw new NotSupportedException("Not in this test");
    }

    protected override void BuildUp(object instance)
    {
        throw new NotSupportedException("Not in this test");
    }

    protected override void Configure()
    {
        base.Configure();
    }

    protected override void OnExit(object sender, EventArgs e)
    {
        base.OnExit(sender, e);
    }

    protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
    {
        base.OnStartup(sender, e);

        _application.Shutdown(0);
    }

    protected override IEnumerable<System.Reflection.Assembly> SelectAssemblies()
    {
        return new[] { typeof(TestBootStrapper).Assembly };
    }

    public IEnumerable<string> Requested
    {
        get { return _requested; }
    }

    public uint ReleasesFor<T>()
    {
        if (_releases.ContainsKey(typeof(T).FullName))
            return _releases[typeof (T).FullName];
        return 0u;
    }
}

[Serializable]
public class SampleViewModel
{
}
于 2012-05-08T20:08:59.633 に答える