Skip to content

Commit

Permalink
Merge 2.11.2-SNAPSHOT-Qualification
Browse files Browse the repository at this point in the history
  • Loading branch information
Vahila committed Feb 20, 2024
2 parents 8156aea + f70394d commit fb80e89
Show file tree
Hide file tree
Showing 27 changed files with 1,149 additions and 1,425 deletions.
188 changes: 93 additions & 95 deletions CONFIGDOC.md

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions examples/Run-MATLAB-Tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ This example shows how to run a suite of MATLAB® unit tests with Jenkins&tra
* Add a build step to the project to run the tests and generate test and coverage artifacts.
* Build the project and examine the test results and the generated artifacts.

The freestyle project runs the tests in the Times Table App MATLAB project (which requires R2019a or later). You can create a working copy of the project files and open the project in MATLAB by running this statement in the Command Window.
The freestyle project runs the tests in the Times Table App MATLAB project (which requires R2019a or later). You can create a working copy of the project files and open the project in MATLAB by running a statement in the Command Window. The statement to run depends on your MATLAB release:

```
matlab.project.example.timesTable
```
R2023a and Earlier | Starting in R2023b
-----------------------------------| ------------------------------------------------
`matlab.project.example.timesTable`| `openExample("matlab/TimesTableProjectExample")`

For more information about the Times Table App example project, see [Explore an Example Project](https://www.mathworks.com/help/matlab/matlab_prog/explore-an-example-project.html).
For more information about the Times Table App project, see [Explore an Example Project](https://www.mathworks.com/help/matlab/matlab_prog/explore-an-example-project.html).

## Prerequisites
To follow the steps in this example:
Expand All @@ -24,37 +24,37 @@ To follow the steps in this example:
Create a new project and configure it by following these steps:
1. In your Jenkins interface, select **New Item** on the left. A new page opens where you can choose the type of your project. Enter a project name, and then click **Freestyle project**. To confirm your choices, click **OK**.

![create_project](https://user-images.githubusercontent.com/48831250/217659170-43474c58-d6a1-44fa-bf72-eafe2aca49bb.png)
![create_project](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/8aa314b3-60fc-4534-bd49-223617ca0542)

2. On the project configuration page, in the **Source Code Management** section, specify the repository that hosts your tests.

![source_control](https://user-images.githubusercontent.com/48831250/217660122-eddabcd5-cab1-4c41-a175-3641457b6d2c.png)
![source_control](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/5befa3c5-6924-4abb-bc34-25ff3328ee47)

3. In the **Build Environment** section, select **Use MATLAB version** and specify the MATLAB version you want to use in the build. If your preferred MATLAB version is not listed under **Use MATLAB version**, enter the full path to its root folder in the **MATLAB root** box.

![build_environment](https://user-images.githubusercontent.com/48831250/217660546-65dc1045-2e4b-4e4b-a1cb-c4b0fedbdbc3.png)
![build_environment](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/c77220c0-a521-41ad-b0e4-76a6f0afce28)

4. In the **Build Steps** section, select **Add build step > Run MATLAB Tests**. Then, specify the artifacts to be generated in the project workspace. In this example, the plugin generates test results in JUnit XML format and code coverage results in Cobertura XML format. Furthermore, to generate the coverage results, the plugin uses only the code in the `source` folder located in the root of the repository. For more information about the build steps provided by the plugin, see [Plugin Configuration Guide](../CONFIGDOC.md).
4. In the **Build Steps** section, select **Add build step > Run MATLAB Tests**. Then, specify the artifacts to generate in the project workspace. In this example, the plugin generates test results in JUnit-style XML format and code coverage results in Cobertura XML format. Furthermore, to generate the coverage results, the plugin uses only the code in the `source` folder located in the root of the repository. For more information about the build steps provided by the plugin, see [Plugin Configuration Guide](../CONFIGDOC.md).

![run_matlab_tests](https://user-images.githubusercontent.com/48831250/217660935-7b6fbcda-5149-4863-983c-64360b8edd07.png)
![run_matlab_tests](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/2ef326b7-9b39-4068-83b9-011cebd52506)

5. In the **Post-build Actions** section, add two post-build actions to publish the JUnit-style test results and the Cobertura code coverage results. For each artifact, provide the path to the report.

![post_build](https://user-images.githubusercontent.com/48831250/217661749-c0ed8340-9fe8-4f88-82f9-f91c2737259d.png)
![post_build](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/d584a290-de93-4a9f-8061-00bc2a435c12)

6. Click **Save** to save the project configuration settings. You can access and modify your settings at a later stage by selecting **Configure** in the project interface, which displays the project name at the upper-left corner of the page.

## Run Tests and Inspect Artifacts
To build your freestyle project, click **Build Now** in the project interface. Jenkins triggers a build, assigns it a number under **Build History**, and runs the build. If the build succeeds, a green icon appears next to the build number. If the build fails, Jenkins adds a red icon. In this example, the build succeeds because all the tests in the Times Table App project pass.
To build your freestyle project, select **Build Now** in the project interface. Jenkins triggers a build, assigns it a number under **Build History**, and runs the build. In this example, the build succeeds because all the tests in the Times Table App project pass.

Navigate to the project workspace by clicking the **Workspace** icon in the project interface. The generated artifacts are in the `matlabTestArtifacts` folder of the workspace.
Navigate to the project workspace by selecting **Workspace** in the project interface. The generated artifacts are in the `matlabTestArtifacts` folder of the workspace.

![workspace](https://user-images.githubusercontent.com/48831250/217663519-d5a4c5bb-43e5-4ff4-ae32-c4b5e1181da7.png)
![workspace](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/5195fb71-6f4f-4261-82c0-501ab953a079)

Click the **Status** icon in the project interface. You can access the published artifacts by clicking the **Latest Test Result** and **Coverage Report** links. For example, click the **Latest Test Result** link to view the published JUnit-style test results. On the test results page, click the **(root)** link in the **All Tests** table. The table expands and lists information for each of the test classes within the Times Table App project.
Select **Status** in the project interface. You can access the published artifacts by clicking the **Latest Test Result** and **Coverage Report** links. For example, click the **Latest Test Result** link to view the published JUnit-style test results. On the test results page, click the **(root)** link in the **All Tests** table. The table expands and lists information for each of the test classes within the Times Table App project.

![test_results](https://user-images.githubusercontent.com/48831250/217663985-14b433e2-7546-40b1-a2e3-34d56f1f11ff.png)
![test_results](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/2dc5142d-b844-436c-8e9e-8f7b90c7b69e)

## See Also
* [Plugin Configuration Guide](../CONFIGDOC.md)<br/>
* [Explore an Example Project (MATLAB)](https://www.mathworks.com/help/matlab/matlab_prog/explore-an-example-project.html)
* [Explore an Example Project (MATLAB)](https://www.mathworks.com/help/matlab/matlab_prog/explore-an-example-project.html)
14 changes: 9 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
Expand All @@ -10,7 +8,7 @@
<relativePath />
</parent>
<artifactId>matlab</artifactId>
<version>2.10.1-SNAPSHOT</version>
<version>2.12.1-SNAPSHOT</version>
<packaging>hpi</packaging>
<developers>
<developer>
Expand Down Expand Up @@ -62,6 +60,12 @@
</dependencies>
</dependencyManagement>
<dependencies>
<!-- JSON Parser -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<!-- Pipeline Step dependencies -->
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down Expand Up @@ -343,4 +347,4 @@
</plugins>
</pluginManagement>
</build>
</project>
</project>
220 changes: 220 additions & 0 deletions src/main/java/com/mathworks/ci/BuildArtifactAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package com.mathworks.ci;

import hudson.FilePath;
import hudson.model.Action;
import hudson.model.Run;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.CheckForNull;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;


public class BuildArtifactAction implements Action {
private Run<?, ?> build;
private FilePath workspace;
private int totalCount;
private int skipCount;
private int failCount;
private static final String ROOT_ELEMENT = "taskDetails";
private static final String BUILD_ARTIFACT_FILE = "buildArtifact.json";

public BuildArtifactAction(Run<?, ?> build, FilePath workspace) {
this.build = build;
this.workspace = workspace;

// Setting the counts of task when Action is created.
try{
setCounts();
} catch (ParseException e) {
throw new RuntimeException(e);
} catch (InterruptedException e){
throw new RuntimeException(e);
}
}

@CheckForNull
@Override
public String getIconFileName() {
return "document.png";
}

@CheckForNull
@Override
public String getDisplayName() {
return "MATLAB Build Results";
}

@CheckForNull
@Override
public String getUrlName() {
return "buildresults";
}

public List<BuildArtifactData> getBuildArtifact() throws ParseException, InterruptedException, IOException {
List<BuildArtifactData> artifactData = new ArrayList<BuildArtifactData>();
FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE));
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) {
Object obj = new JSONParser().parse(reader);
JSONObject jo = (JSONObject) obj;
if (jo.get(ROOT_ELEMENT) instanceof JSONArray) {
JSONArray ja = (JSONArray) jo.get(ROOT_ELEMENT);
Iterator itr2 = ja.iterator();
Iterator<Entry> itr1;
while (itr2.hasNext()) {
BuildArtifactData data = new BuildArtifactData();
itr1 = ((Map) itr2.next()).entrySet().iterator();
while (itr1.hasNext()) {
Entry pair = itr1.next();
iterateAllTaskAttributes(pair, data);
}
artifactData.add(data);
}
} else {
Map ja = ((Map) jo.get(ROOT_ELEMENT));
Iterator<Entry> itr1 = ja.entrySet().iterator();
BuildArtifactData data = new BuildArtifactData();
while (itr1.hasNext()) {
Entry pair = itr1.next();
iterateAllTaskAttributes(pair, data);
}
artifactData.add(data);
}
} catch (IOException e) {
throw new IOException(e.getLocalizedMessage());
}
return artifactData;
}

public void setTotalcount(int totalCount) {
this.totalCount = totalCount;
}

public void setSkipCount(int skipCount) {
this.skipCount = skipCount;
}

public int getTotalCount() {
return this.totalCount;
}

public int getFailCount() {
return this.failCount;
}

public void setFailCount(int failCount) {
this.failCount = failCount;
}

public int getSkipCount() {
return this.skipCount;
}

public Run getOwner() {
return this.build;
}

/**
* @param owner the owner to set
*/
public void setOwner(Run owner) {
this.build = owner;
}

public FilePath getWorkspace() {
return this.workspace;
}

private void setCounts() throws InterruptedException, ParseException {
List<BuildArtifactData> artifactData = new ArrayList<BuildArtifactData>();
FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE));
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) {
Object obj = new JSONParser().parse(reader);
JSONObject jo = (JSONObject) obj;

// getting taskDetails
if (jo.get(ROOT_ELEMENT) instanceof JSONArray) {
JSONArray ja = (JSONArray) jo.get(ROOT_ELEMENT);
Iterator itr2 = ja.iterator();
Iterator<Entry> itr1;
while (itr2.hasNext()) {
BuildArtifactData data = new BuildArtifactData();
itr1 = ((Map) itr2.next()).entrySet().iterator();
while (itr1.hasNext()) {
Entry pair = itr1.next();
iterateFailedSkipped(pair, data);
}
artifactData.add(data);
setTotalcount(artifactData.size());
}
} else {
Map ja = ((Map) jo.get(ROOT_ELEMENT));
Iterator<Entry> itr1 = ja.entrySet().iterator();
BuildArtifactData data = new BuildArtifactData();
while (itr1.hasNext()) {
Entry pair = itr1.next();
iterateFailedSkipped(pair, data);
}
artifactData.add(data);
setTotalcount(artifactData.size());
}
} catch (IOException e) {
e.printStackTrace();
}

// Update the FAILED and SKIPPED task count
int failCount = 0;
int skipCount = 0;
for (BuildArtifactData data : artifactData) {
if (data.getTaskFailed()) {
failCount = failCount + 1;
} else if (data.getTaskSkipped()) {
skipCount = skipCount + 1;
}
}
// Set count for each failed and skipped tasks
setFailCount(failCount);
setSkipCount(skipCount);
}

private void iterateAllTaskAttributes(Entry pair, BuildArtifactData data) {
// Iterates across all task attributes and updates
String key = pair.getKey().toString();
switch(key.toLowerCase()){
case "duration":
data.setTaskDuration(pair.getValue().toString());
break;
case "name" :
data.setTaskName(pair.getValue().toString());
break;
case "description":
data.setTaskDescription(pair.getValue().toString());
break;
case "failed":
data.setTaskFailed((Boolean) pair.getValue());
break;
case "skipped":
data.setTaskSkipped((Boolean) pair.getValue());
break;
default :
break;
}
}

private void iterateFailedSkipped(Entry pair, BuildArtifactData data) {
if (pair.getKey().toString().equalsIgnoreCase("failed")) {
data.setTaskFailed((Boolean) pair.getValue());
} else if (pair.getKey().toString().equalsIgnoreCase("skipped")) {
data.setTaskSkipped((Boolean) pair.getValue());
}
}
}
55 changes: 55 additions & 0 deletions src/main/java/com/mathworks/ci/BuildArtifactData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.mathworks.ci;

public class BuildArtifactData {

private String taskName;
private String taskDuration;
private boolean taskFailed;

private String taskDescription;
private boolean taskSkipped;

public BuildArtifactData() {
}


public String getTaskDuration() {
return this.taskDuration;
}

public void setTaskDuration(String taskDuration) {
this.taskDuration = taskDuration;
}

public String getTaskName() {
return this.taskName;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public boolean getTaskSkipped() {
return this.taskSkipped;
}

public void setTaskSkipped(boolean taskSkipped) {
this.taskSkipped = taskSkipped;
}

public boolean getTaskFailed() {
return this.taskFailed;
}

public void setTaskFailed(boolean taskFailed) {
this.taskFailed = taskFailed;
}

public String getTaskDescription() {
return this.taskDescription;
}

public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
}
Loading

0 comments on commit fb80e89

Please sign in to comment.