diff --git a/src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs b/src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs index 786c6a7283..0c7474bc60 100644 --- a/src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs +++ b/src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs @@ -41,13 +41,21 @@ namespace ICSharpCode.UnitTesting toolStrip.GripStyle = ToolStripGripStyle.Hidden; panel.Controls.Add(toolStrip); + // Add the load solution projects thread ended handler before + // we try to display the open solution so the event does not + // get missed. + ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded; + OnAddedLoadSolutionProjectsThreadEndedHandler(); + // Display currently open solution. - Solution openSolution = ProjectService.OpenSolution; - if (openSolution != null) { - SolutionLoaded(openSolution); + + if (!IsParserLoadingSolution) { + Solution openSolution = GetOpenSolution(); + if (openSolution != null) { + SolutionLoaded(openSolution); + } } - ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded; ParserService.ParseInformationUpdated += ParseInformationUpdated; ProjectService.SolutionClosed += SolutionClosed; ProjectService.SolutionFolderRemoved += SolutionFolderRemoved; @@ -161,26 +169,67 @@ namespace ICSharpCode.UnitTesting } } + /// + /// Protected method so we can test this method. + /// protected void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit) { treeView.UpdateParseInfo(oldUnit, newUnit); } + /// + /// Virtual method so we can override this method and return + /// a dummy toolstrip when testing. + /// protected virtual ToolStrip CreateToolStrip(string name) { return ToolbarService.CreateToolStrip(treeView, "/SharpDevelop/Pads/UnitTestsPad/Toolbar"); } + /// + /// Virtual method so we can override this method and return + /// a dummy ContextMenuStrip when testing. + /// protected virtual ContextMenuStrip CreateContextMenu(string name) { return MenuService.CreateContextMenu(treeView, "/SharpDevelop/Pads/UnitTestsPad/ContextMenu"); } + /// + /// Virtual method so we can override this method and return + /// a dummy TestTreeView when testing. + /// protected virtual TestTreeView CreateTestTreeView() { return new TestTreeView(); } + /// + /// Gets the currently open solution. + /// + protected virtual Solution GetOpenSolution() + { + return ProjectService.OpenSolution; + } + + /// + /// Determines whether the parser is currently still loading the + /// solution. + /// + protected virtual bool IsParserLoadingSolution { + get { + return ParserService.LoadSolutionProjectsThreadRunning; + } + } + + /// + /// Indicates that an event handler for the ParserService's + /// LoadSolutionProjectsThreadEnded event has been added + /// + protected virtual void OnAddedLoadSolutionProjectsThreadEndedHandler() + { + } + void SolutionClosed(object source, EventArgs e) { SolutionClosed(); diff --git a/src/AddIns/Misc/UnitTesting/Test/Tree/OpenUnitTestsPadWithSolutionOpenTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Tree/OpenUnitTestsPadWithSolutionOpenTestFixture.cs new file mode 100644 index 0000000000..4a11aaf9b4 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Tree/OpenUnitTestsPadWithSolutionOpenTestFixture.cs @@ -0,0 +1,67 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Forms; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Tree +{ + /// + /// Tests that if the parser is still running then we do not + /// add the solution to the unit tests tree. + /// + [TestFixture] + public class OpenUnitTestsPadWithSolutionOpenTestFixture + { + DerivedUnitTestsPad pad; + + [TestFixtureSetUp] + public void SetUp() + { + Solution solution = new Solution(); + MockCSharpProject project = new MockCSharpProject(); + MockProjectContent projectContent = new MockProjectContent(); + projectContent.Project = project; + projectContent.Language = LanguageProperties.None; + ReferenceProjectItem refProjectItem = new ReferenceProjectItem(project); + refProjectItem.Include = "NUnit.Framework"; + ProjectService.AddProjectItem(project, refProjectItem); + solution.Folders.Add(project); + + pad = new DerivedUnitTestsPad(solution); + } + + [TestFixtureTearDown] + public void TearDown() + { + pad.Dispose(); + } + + [Test] + public void NoSolutionAddedToTree() + { + Assert.AreEqual(0, pad.TestTreeView.GetProjects().Length); + } + + /// + /// The LoadSolutionProjectsThreadEnded event handler needs to be + /// added before the unit tests pad checks the + /// LoadSolutionProjectsThreadRunning flag so we do not miss the + /// event. + /// + [Test] + public void ParserServiceLoadSolutionProjectsThreadEndedHandled() + { + Assert.IsTrue(pad.LoadSolutionProjectsThreadEndedHandled); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs index 2e0b5cdf62..659c1e5280 100644 --- a/src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs +++ b/src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs @@ -21,17 +21,24 @@ namespace UnitTesting.Tests.Tree /// a new solution is opened. /// [TestFixture] - public class SolutionOpenedTestFixture : UnitTestsPad + public class SolutionOpenedTestFixture { + DerivedUnitTestsPad pad; Solution solution; MSBuildBasedProject project; - MockProjectContent projectContent = new MockProjectContent(); + + [TestFixtureSetUp] + public void SetUpFixture() + { + pad = new DerivedUnitTestsPad(); + } [SetUp] public void Init() { solution = new Solution(); project = new MockCSharpProject(); + MockProjectContent projectContent = pad.ProjectContent; projectContent.Project = project; projectContent.Language = LanguageProperties.None; ReferenceProjectItem refProjectItem = new ReferenceProjectItem(project); @@ -39,29 +46,37 @@ namespace UnitTesting.Tests.Tree ProjectService.AddProjectItem(project, refProjectItem); solution.Folders.Add(project); - base.SolutionLoaded(solution); + pad.CallSolutionLoaded(solution); + } + + [TestFixtureTearDown] + public void TearDownFixture() + { + if (pad != null) { + pad.Dispose(); + } } [Test] public void TestTreeHasNodes() { - Assert.AreEqual(1, base.TestTreeView.Nodes.Count); + Assert.AreEqual(1, pad.TestTreeView.Nodes.Count); } [Test] public void CloseSolution() { - base.SolutionClosed(); + pad.CallSolutionClosed(); - Assert.AreEqual(0, base.TestTreeView.Nodes.Count); + Assert.AreEqual(0, pad.TestTreeView.Nodes.Count); } [Test] public void SolutionFolderRemoved() { - base.SolutionFolderRemoved(project); + pad.CallSolutionFolderRemoved(project); - Assert.AreEqual(0, base.TestTreeView.Nodes.Count); + Assert.AreEqual(0, pad.TestTreeView.Nodes.Count); } [Test] @@ -73,9 +88,9 @@ namespace UnitTesting.Tests.Tree refProjectItem.Include = "NUnit.Framework"; ProjectService.AddProjectItem(project, refProjectItem); - base.ProjectAdded(project); + pad.CallProjectAdded(project); - Assert.AreEqual(2, base.TestTreeView.Nodes.Count); + Assert.AreEqual(2, pad.TestTreeView.Nodes.Count); } [Test] @@ -84,9 +99,9 @@ namespace UnitTesting.Tests.Tree ProjectItem refProjectItem = project.Items[0]; ProjectService.RemoveProjectItem(project, refProjectItem); - base.ProjectItemRemoved(refProjectItem); + pad.CallProjectItemRemoved(refProjectItem); - Assert.AreEqual(0, base.TestTreeView.Nodes.Count); + Assert.AreEqual(0, pad.TestTreeView.Nodes.Count); } [Test] @@ -95,20 +110,20 @@ namespace UnitTesting.Tests.Tree IProject project = new MockCSharpProject(); project.Name = "NewProject"; - base.ProjectAdded(project); + pad.CallProjectAdded(project); // Project should not be added at first. - Assert.AreEqual(1, base.TestTreeView.Nodes.Count); + Assert.AreEqual(1, pad.TestTreeView.Nodes.Count); ReferenceProjectItem refProjectItem = new ReferenceProjectItem(project); refProjectItem.Include = "NUnit.Framework"; ProjectService.AddProjectItem(project, refProjectItem); - base.ProjectItemAdded(refProjectItem); + pad.CallProjectItemAdded(refProjectItem); // Project should be added since it has a reference to // NUnit. - Assert.AreEqual(2, base.TestTreeView.Nodes.Count); + Assert.AreEqual(2, pad.TestTreeView.Nodes.Count); } [Test] @@ -120,32 +135,32 @@ namespace UnitTesting.Tests.Tree refProjectItem.Include = "NUnit.Framework"; ProjectService.AddProjectItem(project, refProjectItem); - base.ProjectAdded(project); + pad.CallProjectAdded(project); // Add a second NUnit.Framework reference. refProjectItem = new ReferenceProjectItem(project); refProjectItem.Include = "NUnit.Framework"; ProjectService.AddProjectItem(project, refProjectItem); - base.ProjectItemAdded(refProjectItem); + pad.CallProjectItemAdded(refProjectItem); - Assert.AreEqual(2, base.TestTreeView.Nodes.Count); + Assert.AreEqual(2, pad.TestTreeView.Nodes.Count); } [Test] public void ParserInfoUpdated() { - DefaultCompilationUnit newUnit = new DefaultCompilationUnit(projectContent); + DefaultCompilationUnit newUnit = new DefaultCompilationUnit(pad.ProjectContent); MockClass mockClass = new MockClass("MyTestFixture"); mockClass.Attributes.Add(new MockAttribute("TestFixture")); - mockClass.ProjectContent = projectContent; + mockClass.ProjectContent = pad.ProjectContent; mockClass.SetCompoundClass(mockClass); newUnit.Classes.Add(mockClass); - ExtTreeNode rootNode = (ExtTreeNode)base.TestTreeView.Nodes[0]; + ExtTreeNode rootNode = (ExtTreeNode)pad.TestTreeView.Nodes[0]; rootNode.Expanding(); - base.UpdateParseInfo(null, newUnit); + pad.CallUpdateParseInfo(null, newUnit); Assert.AreEqual(1, rootNode.Nodes.Count); Assert.AreEqual("MyTestFixture", rootNode.Nodes[0].Text); @@ -154,17 +169,17 @@ namespace UnitTesting.Tests.Tree [Test] public void GetTestProjectFromProject() { - TestProjectTreeNode projectNode = (TestProjectTreeNode)base.TestTreeView.Nodes[0]; + TestProjectTreeNode projectNode = (TestProjectTreeNode)pad.TestTreeView.Nodes[0]; TestProject expectedTestProject = projectNode.TestProject; - Assert.AreSame(expectedTestProject, base.TestTreeView.GetTestProject(project)); + Assert.AreSame(expectedTestProject, pad.TestTreeView.GetTestProject(project)); } [Test] public void GetTestProjectFromUnknownProject() { IProject project = new MockCSharpProject(); - Assert.IsNull(base.TestTreeView.GetTestProject(project)); + Assert.IsNull(pad.TestTreeView.GetTestProject(project)); } /// @@ -175,7 +190,7 @@ namespace UnitTesting.Tests.Tree public void ClassNodeAddedAfterProjectNodeExpanded() { // Expand the project node. - TestProjectTreeNode projectNode = (TestProjectTreeNode)base.TestTreeView.Nodes[0]; + TestProjectTreeNode projectNode = (TestProjectTreeNode)pad.TestTreeView.Nodes[0]; projectNode.Expanding(); // Add a new class to a non-empty namespace so it gets @@ -203,7 +218,7 @@ namespace UnitTesting.Tests.Tree ClassNodeAddedAfterProjectNodeExpanded(); // Expand the namespace node. - TestProjectTreeNode projectNode = (TestProjectTreeNode)base.TestTreeView.Nodes[0]; + TestProjectTreeNode projectNode = (TestProjectTreeNode)pad.TestTreeView.Nodes[0]; TestNamespaceTreeNode parentNamespaceNode = (TestNamespaceTreeNode)projectNode.Nodes[0]; parentNamespaceNode.Expanding(); @@ -239,7 +254,7 @@ namespace UnitTesting.Tests.Tree public void EmptyNamespaceNodesRemoved() { // Expand the project node. - TestProjectTreeNode projectNode = (TestProjectTreeNode)base.TestTreeView.Nodes[0]; + TestProjectTreeNode projectNode = (TestProjectTreeNode)pad.TestTreeView.Nodes[0]; projectNode.Expanding(); // Add a new class to a non-empty namespace so it gets @@ -288,7 +303,7 @@ namespace UnitTesting.Tests.Tree public void EmptyNamespaceNodesRemovedWhenChildNamespaceNodeNotExpanded() { // Expand the project node. - TestProjectTreeNode projectNode = (TestProjectTreeNode)base.TestTreeView.Nodes[0]; + TestProjectTreeNode projectNode = (TestProjectTreeNode)pad.TestTreeView.Nodes[0]; projectNode.Expanding(); // Add a new class to a non-empty namespace so it gets @@ -314,35 +329,16 @@ namespace UnitTesting.Tests.Tree "Namespace nodes should have been removed from project node."); } - /// - /// Returns a dummy toolstrip so the UnitTestsPad can be - /// tested. If the default method is called the AddInTree - /// is referenced which is not available during testing. - /// - protected override ToolStrip CreateToolStrip(string name) - { - return new ToolStrip(); - } - - /// - /// Returns a dummy ContextMenuStrip so the UnitTestsPad can be - /// tested. If the default method is called the AddInTree - /// is referenced which is not available during testing. - /// - protected override ContextMenuStrip CreateContextMenu(string name) + [Test] + public void IsParserLoadingSolutionCalled() { - return new ContextMenuStrip(); + Assert.IsTrue(pad.IsParserLoadingSolutionCalled); } - /// - /// Returns a dummy tree view where we can mock the - /// IProjectContent that will be used by the TestTreeView. - /// - protected override TestTreeView CreateTestTreeView() + [Test] + public void GetOpenSolutionCalled() { - DummyParserServiceTestTreeView treeView = new DummyParserServiceTestTreeView(); - treeView.AddProjectContentForProject(projectContent); - return treeView; + Assert.IsTrue(pad.GetOpenSolutionCalled); } } } diff --git a/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj b/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj index 80724b9e76..22b2ebc4ea 100644 --- a/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj +++ b/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj @@ -57,6 +57,8 @@ + + diff --git a/src/AddIns/Misc/UnitTesting/Test/Utils/DerivedUnitTestsPad.cs b/src/AddIns/Misc/UnitTesting/Test/Utils/DerivedUnitTestsPad.cs new file mode 100644 index 0000000000..20899cff5e --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Utils/DerivedUnitTestsPad.cs @@ -0,0 +1,157 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Forms; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; + +namespace UnitTesting.Tests.Utils +{ + /// + /// Class that derives from UnitTestsPad so we can access protected + /// methods and test it. + /// + public class DerivedUnitTestsPad : UnitTestsPad + { + bool getOpenSolutionCalled; + bool isParserLoadingSolutionCalled; + MockProjectContent projectContent = new MockProjectContent(); + Solution openSolution; + bool loadSolutionProjectsThreadEndedHandled; + bool addedLoadSolutionProjectsThreadEndedHandler; + + public DerivedUnitTestsPad(Solution openSolution) + { + this.openSolution = openSolution; + } + + public DerivedUnitTestsPad() + { + } + + /// + /// Gets the project content to be used when creating the + /// derived test tree view. + /// + public MockProjectContent ProjectContent { + get { + return projectContent; + } + } + + public bool GetOpenSolutionCalled { + get { + return getOpenSolutionCalled; + } + } + + public bool IsParserLoadingSolutionCalled { + get { + return isParserLoadingSolutionCalled; + } + } + + /// + /// Checks whether the ParserService's LoadSolutionProjectsThreadEnded event + /// is mapped to an event handler before IsParserLoadingSolution is + /// called. This ensures we do not miss this event. + /// + public bool LoadSolutionProjectsThreadEndedHandled { + get { + return loadSolutionProjectsThreadEndedHandled; + } + } + + public void CallSolutionLoaded(Solution solution) + { + base.SolutionLoaded(solution); + } + + public void CallSolutionClosed() + { + base.SolutionClosed(); + } + + public void CallProjectItemRemoved(ProjectItem item) + { + base.ProjectItemRemoved(item); + } + + public void CallProjectItemAdded(ProjectItem item) + { + base.ProjectItemAdded(item); + } + + public void CallProjectAdded(IProject project) + { + base.ProjectAdded(project); + } + + public void CallSolutionFolderRemoved(ISolutionFolder folder) + { + base.SolutionFolderRemoved(folder); + } + + public void CallUpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit) + { + base.UpdateParseInfo(oldUnit, newUnit); + } + + /// + /// Returns a dummy toolstrip so the UnitTestsPad can be + /// tested. If the default method is called the AddInTree + /// is referenced which is not available during testing. + /// + protected override ToolStrip CreateToolStrip(string name) + { + return new ToolStrip(); + } + + /// + /// Returns a dummy ContextMenuStrip so the UnitTestsPad can be + /// tested. If the default method is called the AddInTree + /// is referenced which is not available during testing. + /// + protected override ContextMenuStrip CreateContextMenu(string name) + { + return new ContextMenuStrip(); + } + + /// + /// Returns a dummy tree view where we can mock the + /// IProjectContent that will be used by the TestTreeView. + /// + protected override TestTreeView CreateTestTreeView() + { + DummyParserServiceTestTreeView treeView = new DummyParserServiceTestTreeView(); + treeView.AddProjectContentForProject(projectContent); + return treeView; + } + + protected override Solution GetOpenSolution() + { + getOpenSolutionCalled = true; + return openSolution; + } + + protected override bool IsParserLoadingSolution { + get { + loadSolutionProjectsThreadEndedHandled = addedLoadSolutionProjectsThreadEndedHandler; + isParserLoadingSolutionCalled = true; + return false; + } + } + + protected override void OnAddedLoadSolutionProjectsThreadEndedHandler() + { + addedLoadSolutionProjectsThreadEndedHandler = true; + } + } +}