Browse Source

Fixed SD2-1233. When opening the Unit Tests pad after just opening a solution, before the parser has finished parsing the contained projects, the Unit Tests pad no longer adds projects to the test tree view. Before the parser has finished parsing a project it has no associated project content. Previously this caused the test tree to throw a null reference exception.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2142 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 19 years ago
parent
commit
4800ae7268
  1. 57
      src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs
  2. 67
      src/AddIns/Misc/UnitTesting/Test/Tree/OpenUnitTestsPadWithSolutionOpenTestFixture.cs
  3. 106
      src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs
  4. 2
      src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj
  5. 157
      src/AddIns/Misc/UnitTesting/Test/Utils/DerivedUnitTestsPad.cs

57
src/AddIns/Misc/UnitTesting/Src/UnitTestsPad.cs

@ -41,13 +41,21 @@ namespace ICSharpCode.UnitTesting @@ -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 @@ -161,26 +169,67 @@ namespace ICSharpCode.UnitTesting
}
}
/// <summary>
/// Protected method so we can test this method.
/// </summary>
protected void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit)
{
treeView.UpdateParseInfo(oldUnit, newUnit);
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy toolstrip when testing.
/// </summary>
protected virtual ToolStrip CreateToolStrip(string name)
{
return ToolbarService.CreateToolStrip(treeView, "/SharpDevelop/Pads/UnitTestsPad/Toolbar");
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy ContextMenuStrip when testing.
/// </summary>
protected virtual ContextMenuStrip CreateContextMenu(string name)
{
return MenuService.CreateContextMenu(treeView, "/SharpDevelop/Pads/UnitTestsPad/ContextMenu");
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy TestTreeView when testing.
/// </summary>
protected virtual TestTreeView CreateTestTreeView()
{
return new TestTreeView();
}
/// <summary>
/// Gets the currently open solution.
/// </summary>
protected virtual Solution GetOpenSolution()
{
return ProjectService.OpenSolution;
}
/// <summary>
/// Determines whether the parser is currently still loading the
/// solution.
/// </summary>
protected virtual bool IsParserLoadingSolution {
get {
return ParserService.LoadSolutionProjectsThreadRunning;
}
}
/// <summary>
/// Indicates that an event handler for the ParserService's
/// LoadSolutionProjectsThreadEnded event has been added
/// </summary>
protected virtual void OnAddedLoadSolutionProjectsThreadEndedHandler()
{
}
void SolutionClosed(object source, EventArgs e)
{
SolutionClosed();

67
src/AddIns/Misc/UnitTesting/Test/Tree/OpenUnitTestsPadWithSolutionOpenTestFixture.cs

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
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
{
/// <summary>
/// Tests that if the parser is still running then we do not
/// add the solution to the unit tests tree.
/// </summary>
[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);
}
/// <summary>
/// The LoadSolutionProjectsThreadEnded event handler needs to be
/// added before the unit tests pad checks the
/// LoadSolutionProjectsThreadRunning flag so we do not miss the
/// event.
/// </summary>
[Test]
public void ParserServiceLoadSolutionProjectsThreadEndedHandled()
{
Assert.IsTrue(pad.LoadSolutionProjectsThreadEndedHandled);
}
}
}

106
src/AddIns/Misc/UnitTesting/Test/Tree/SolutionOpenedTestFixture.cs

@ -21,17 +21,24 @@ namespace UnitTesting.Tests.Tree @@ -21,17 +21,24 @@ namespace UnitTesting.Tests.Tree
/// a new solution is opened.
/// </summary>
[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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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));
}
/// <summary>
@ -175,7 +190,7 @@ namespace UnitTesting.Tests.Tree @@ -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 @@ -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 @@ -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 @@ -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 @@ -314,35 +329,16 @@ namespace UnitTesting.Tests.Tree
"Namespace nodes should have been removed from project node.");
}
/// <summary>
/// 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.
/// </summary>
protected override ToolStrip CreateToolStrip(string name)
{
return new ToolStrip();
}
/// <summary>
/// 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.
/// </summary>
protected override ContextMenuStrip CreateContextMenu(string name)
[Test]
public void IsParserLoadingSolutionCalled()
{
return new ContextMenuStrip();
Assert.IsTrue(pad.IsParserLoadingSolutionCalled);
}
/// <summary>
/// Returns a dummy tree view where we can mock the
/// IProjectContent that will be used by the TestTreeView.
/// </summary>
protected override TestTreeView CreateTestTreeView()
[Test]
public void GetOpenSolutionCalled()
{
DummyParserServiceTestTreeView treeView = new DummyParserServiceTestTreeView();
treeView.AddProjectContentForProject(projectContent);
return treeView;
Assert.IsTrue(pad.GetOpenSolutionCalled);
}
}
}

2
src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj

@ -57,6 +57,8 @@ @@ -57,6 +57,8 @@
<Compile Include="AssemblyInfo.cs" />
<Compile Include="NamespaceFilterTests.cs" />
<Compile Include="TestableConditionTests.cs" />
<Compile Include="Tree\OpenUnitTestsPadWithSolutionOpenTestFixture.cs" />
<Compile Include="Utils\DerivedUnitTestsPad.cs" />
<Compile Include="Utils\MockTestCase.cs" />
<Compile Include="Utils\MockTestTreeView.cs" />
<Compile Include="Utils\MockMember.cs" />

157
src/AddIns/Misc/UnitTesting/Test/Utils/DerivedUnitTestsPad.cs

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.UnitTesting;
namespace UnitTesting.Tests.Utils
{
/// <summary>
/// Class that derives from UnitTestsPad so we can access protected
/// methods and test it.
/// </summary>
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()
{
}
/// <summary>
/// Gets the project content to be used when creating the
/// derived test tree view.
/// </summary>
public MockProjectContent ProjectContent {
get {
return projectContent;
}
}
public bool GetOpenSolutionCalled {
get {
return getOpenSolutionCalled;
}
}
public bool IsParserLoadingSolutionCalled {
get {
return isParserLoadingSolutionCalled;
}
}
/// <summary>
/// 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.
/// </summary>
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);
}
/// <summary>
/// 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.
/// </summary>
protected override ToolStrip CreateToolStrip(string name)
{
return new ToolStrip();
}
/// <summary>
/// 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.
/// </summary>
protected override ContextMenuStrip CreateContextMenu(string name)
{
return new ContextMenuStrip();
}
/// <summary>
/// Returns a dummy tree view where we can mock the
/// IProjectContent that will be used by the TestTreeView.
/// </summary>
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;
}
}
}
Loading…
Cancel
Save