Skip to content

Commit

Permalink
improved performance by enabling project build and restore to be togg… (
Browse files Browse the repository at this point in the history
#13)

* improved performance by enabling project build and restore to be toggled; Fixed the display of multiple test projects in the explorer.

* updated changelog.

* changed the test discovery logic to include more strings and find tests even with multiple projects.

* updated to account for the output when build is enabled.

* realized a more obvious solution; dotnet test -t prefixes actual discovered tests with spaces.

* Polished the changes, broke the directory path logic up for consistency with other 'options' functions.

* fixed path resolving logic to remove redundant comparison.
  • Loading branch information
ciel authored and formulahendry committed Aug 23, 2017
1 parent b6711f7 commit d6fc419
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 46 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
out
node_modules
.DS_Store
npm-debug.log
npm-debug.log
*.ini
yarn.*
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.1 (2017-08-22)
* Support for multiple projects
* Added options for disabling rebuild and restore

## 0.1.0 (2017-08-21)
* Support tree view for xUnit
* Evaluate working dir before running all tests
Expand All @@ -11,4 +15,4 @@
* Not show pop-up error message

## 0.0.1 (2017-08-12)
* Initial Release
* Initial Release
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
## Settings

* `dotnet-test-explorer.testProjectPath`: Folder path of .NET Core test project. You could set the full path or the relative path to the workspace root path. (Default is **""**)
* `dotnet-test-explorer.msbuildRootTestMsg`: A root message for dotnet test command. In English it is 'The following Tests are available:' but for example in Polish it is 'Dostępne są następujące testy:'
* `dotnet-test-explorer.useTreeView`: If false, will list all tests as the full namespace. When set to true a tree will be created based on the namespaces of the tests. (Only xUnit tests will be listed in a tree view) (Default is **true**)
* `dotnet-test-explorer.build`: If true, projects will be built when refreshing the test explorer. (Default is **true**)
* `dotnet-test-explorer.restore`: If true, dotnet restore will run when refreshing the test explorer. (Default is **true**)

## Telemetry data

Expand Down
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "dotnet-test-explorer",
"displayName": ".NET Core Test Explorer",
"description": "Test Explorer for .NET Core",
"version": "0.1.0",
"version": "0.1.1",
"publisher": "formulahendry",
"license": "MIT",
"icon": "logo.png",
Expand Down Expand Up @@ -92,15 +92,20 @@
"default": "",
"description": "Folder path of .NET Core test project. You could set the full path or the relative path to the workspace root path."
},
"dotnet-test-explorer.msbuildRootTestMsg": {
"type": "string",
"default": "",
"description": "A root message for dotnet test command. In English it is 'The following Tests are available:' but for example in Polish it is 'Dostępne są następujące testy:'"
},
"dotnet-test-explorer.useTreeView": {
"type": "boolean",
"default": true,
"description": "If false, will list all tests as the full namespace. When set to true a tree will be created based on the namespaces of the tests. (Only xUnit tests will be listed in a tree view)"
},
"dotnet-test-explorer.build": {
"type": "boolean",
"default": true,
"description": "If true, projects will be built when refreshing the test explorer."
},
"dotnet-test-explorer.restore": {
"type": "boolean",
"default": true,
"description": "If true, dotnet restore will run when refreshing the test explorer."
}
}
}
Expand Down
157 changes: 121 additions & 36 deletions src/dotnetTestExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,51 @@ export class DotnetTestExplorer implements TreeDataProvider<TestNode> {
public _onDidChangeTreeData: vscode.EventEmitter<any> = new vscode.EventEmitter<any>();
public readonly onDidChangeTreeData: vscode.Event<any> = this._onDidChangeTreeData.event;

/**
* The directory where the dotnet-cli will
* execute commands.
*/
private testDirectoryPath: string;

constructor(private context: vscode.ExtensionContext) {
constructor(private context: vscode.ExtensionContext) {}

/**
* @description
* Refreshes the test explorer pane by running the
* `dotnet test` command and requesting information about
* discovered tests.
* @summary
* This method can cause the project to rebuild or try
* to do a restore, so it can be very slow.
*/
public refreshTestExplorer(): void {
this._onDidChangeTreeData.fire();
AppInsightsClient.sendEvent("refreshTestExplorer");
}

/**
* @description
* Runs all tests discovered in the project directory.
* @summary
* This method can cause the project to rebuild or try
* to do a restore, so it can be very slow.
*/
public runAllTests(): void {
this.evaluateTestDirectory();
Executor.runInTerminal(`dotnet test${this.checkBuildOption()}${this.checkRestoreOption()}`, this.testDirectoryPath);
AppInsightsClient.sendEvent("runAllTests");
}

/**
* @description
* Runs a specific test discovered from the project directory.
* @summary
* This method can cause the project to rebuild or try
* to do a restore, so it can be very slow.
*/
public runTest(test: TestNode): void {
Executor.runInTerminal(`dotnet test${this.checkBuildOption()}${this.checkRestoreOption()} --filter FullyQualifiedName~${test.fullName}`, this.testDirectoryPath);
AppInsightsClient.sendEvent("runTest");
}

public getTreeItem(element: TestNode): TreeItem {
Expand Down Expand Up @@ -62,22 +104,6 @@ export class DotnetTestExplorer implements TreeDataProvider<TestNode> {
});
}

public refreshTestExplorer(): void {
this._onDidChangeTreeData.fire();
AppInsightsClient.sendEvent("refreshTestExplorer");
}

public runAllTests(): void {
this.evaluateTestDirectory();
Executor.runInTerminal("dotnet test", this.testDirectoryPath);
AppInsightsClient.sendEvent("runAllTests");
}

public runTest(test: TestNode): void {
Executor.runInTerminal(`dotnet test --filter FullyQualifiedName~${test.fullName}`, this.testDirectoryPath);
AppInsightsClient.sendEvent("runTest");
}

private addToObject(container: object, parts: string[]): void {
const title = parts.splice(0, 1)[0];

Expand Down Expand Up @@ -111,28 +137,69 @@ export class DotnetTestExplorer implements TreeDataProvider<TestNode> {
}
}

/**
* @description
* Checks to see if the options specify that the dotnet-cli
* should run `dotnet build` before loading tests.
* @summary
* If this is set to **false**, then `--no-build` is passed into the
* command line arguments. It is prefixed by a space only if **false**.
*/
private checkBuildOption(): string {
const option = Utility.getConfiguration().get<boolean>("build");
return option ? "" : " --no-build";
}

/**
* @description
* Checks to see if the options specify that the dotnet-cli
* should run `dotnet restore` before loading tests.
* @summary
* If this is set to **false**, then `--no-restore` is passed into the
* command line arguments. It is prefixed by a space only if **false**.
*/
private checkRestoreOption(): string {
const option = Utility.getConfiguration().get<boolean>("restore");
return option ? "" : " --no-restore";
}

/**
* @description
* Checks to see if the options specify a directory to run the
* dotnet-cli test commands in.
* @summary
* This will use the project root by default.
*/
private checkTestDirectoryOption(): string {
const option = Utility.getConfiguration().get<string>("testProjectPath");
return option ? option : vscode.workspace.rootPath;
}

/**
* @description
* Executes the `dotnet test -t` command from the dotnet-cli to
* try and discover tests.
*/
private loadTestStrings(): Thenable<string[]> {
this.evaluateTestDirectory();

let msBuildRootTestMsg = Utility.getConfiguration().get<string>("msbuildRootTestMsg");
msBuildRootTestMsg = msBuildRootTestMsg ? msBuildRootTestMsg : "The following Tests are available:";

return new Promise((c, e) => {
try {
const testStrings = Executor
.execSync("dotnet test -t", this.testDirectoryPath)
const results = Executor
.execSync(`dotnet test -t -v=q${this.checkBuildOption()}${this.checkRestoreOption()}`, this.testDirectoryPath)
.split(/[\r\n]+/g)
.filter((item) => item && !item.startsWith("[xUnit.net"))
/*
* The dotnet-cli prefixes all discovered unit tests
* with whitespace. We can use this to drop any lines of
* text that are not relevant, even in complicated project
* structures.
**/
.filter((item) => item && item.startsWith(" "))
.sort((a, b) => a > b ? 1 : b > a ? - 1 : 0 )
.map((item) => item.trim());

const index = testStrings.indexOf(msBuildRootTestMsg);
if (index > -1) {
const result = testStrings
.slice(index + 1)
.sort((a, b) => a > b ? 1 : b > a ? -1 : 0);
c(results);

c(result);
}
} catch (error) {
return e(["Please open or set the test project", "and ensure your project compiles."]);
}
Expand All @@ -141,12 +208,30 @@ export class DotnetTestExplorer implements TreeDataProvider<TestNode> {
});
}

/**
* @description
* Checks to see if the @see{vscode.workspace.rootPath} is
* the same as the directory given, and resolves the correct
* string to it if not.
* @param dir
* The directory specified in the options.
*/
private resolvePath(dir: string): string {
return path.isAbsolute(dir)
? dir
: path.resolve(vscode.workspace.rootPath, dir);
}

/**
* @description
* Discover the directory where the dotnet-cli
* will execute commands, taken from the options.
* @summary
* This will be the @see{vscode.workspace.rootPath}
* by default.
*/
private evaluateTestDirectory(): void {
const testProjectPath = Utility.getConfiguration().get<string>("testProjectPath");
let testProjectFullPath = testProjectPath ? testProjectPath : vscode.workspace.rootPath;
if (!path.isAbsolute(testProjectFullPath)) {
testProjectFullPath = path.resolve(vscode.workspace.rootPath, testProjectPath);
}
this.testDirectoryPath = testProjectFullPath;
const testProjectFullPath = this.checkTestDirectoryOption();
this.testDirectoryPath = this.resolvePath(testProjectFullPath);
}
}
2 changes: 1 addition & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"no-empty": false,
"object-literal-sort-keys": false
}
}
}

0 comments on commit d6fc419

Please sign in to comment.