Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/broken_links_checker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
}
]
}' > ./target/broken_links_checker.json
- uses: tcort/github-action-markdown-link-check@v1
- uses: tcort/github-action-markdown-link-check@e7c7a18363c842693fadde5d41a3bd3573a7a225
with:
use-quiet-mode: "yes"
use-verbose-mode: "yes"
Expand Down
39 changes: 11 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## What is OpenFastTrace?

OpenFastTrace (short OFT) is a requirement tracing suite. Requirement tracing keeps track of whether you actually implemented everything you planned to in your specifications. It also identifies obsolete parts of your product and helps you to get rid of them.
OpenFastTrace (short OFT) is a requirement management and tracing suite. Requirement tracing keeps track of whether you actually implemented everything you planned to in your specifications. It also identifies obsolete parts of your product and helps you to get rid of them.

You can learn more about requirement tracing and how to use OpenFastTrace in the [user guide](doc/user_guide/user_guide.md).

Expand Down Expand Up @@ -31,29 +31,30 @@ Sonarcloud status:

**User Guides and Tools**

* [📖 User Guide](doc/user_guide/user_guide.md)
* [📚 Terminology](doc/terminology.md)
* [🔌 Extending OpenFastTrace With Plugins](doc/plugins.md)
* [📖 User Guide](https://openfasttrace.itsallcode.org/user_guide/user_guide.html)
* [📚 Terminology](https://openfasttrace.itsallcode.org/terminology.html)
* [🔌 Extending OpenFastTrace With Plugins](https://openfasttrace.itsallcode.org/plugins.html)
* [💲 Command Line Usage](core/src/main/resources/usage.txt)
* [🛠 IntelliJ Plugin (PyCharm, Clion, etc.)](https://github.com/itsallcode/openfasttrace-intellij-plugin)
* [🤖 Agent Skills](.agents/skills)
* [🛡️ Security Policy](SECURITY.md)
* [♻️ Project Lifecycle and Deprecations](doc/user_guide/project_lifecycle.md)
* [♻️ Project Lifecycle and Deprecations](doc/user_guide/product_lifecycle/product_lifecycle.md)

**News and Discussions**

* [🌐 Homepage](https://openfasttrace.itsallcode.org)
* [📢 Blog](https://blog.itsallcode.org/)
* [➕ Changelog](doc/changes/changes.md)
* [📅 Upcoming Milestones](https://github.com/orgs/itsallcode/projects/3/views/3)
* [🗨️ Discussion Board](https://github.com/itsallcode/openfasttrace/discussions)
* [🐘 OpenFastTrace@mastodon.social](https://mastodon.social/@OpenFastTrace)
* [✨ OpenFastTrace Stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories)
* [ℹ️ About us](doc/about_us.md)
* [ℹ️ About us](https://openfasttrace.itsallcode.org/about_us.html)

**Information for Contributors**

* [🎟️ Project Board](https://github.com/orgs/itsallcode/projects/3/views/1)
* [🦮 Developer Guide](doc/developer_guide/developer_guide.md)
* [🦮 Developer Guide](https://openfasttrace.itsallcode.org/developer_guide/developer_guide.html)
* [🔌 Plugin Developer Guide](doc/developer_guide/plugin_developer_guide.md)
* [🎁 Contributing Guide](CONTRIBUTING.md)
* [🤝 Code of Conduct](CODE_OF_CONDUCT.md)
Expand Down Expand Up @@ -94,27 +95,9 @@ Check our [developer guide](doc/developer_guide/developer_guide.md#getting-the-o
OpenFastTrace 4.0.0 and above only needs a Java 17 (or later) runtime environment to run. OpenFastTrace until version 3.x.x supported Java 11. Versions prior to that ran with Java 8.
Note that only the latest version of OFT is actively supported.

#### Installation of Runtime Dependencies on Linux

##### Ubuntu or Debian

If you just want to run OFT:

apt-get install openjdk-17-jre

### Installation via Homebrew

On macOS or Linux, install OpenFastTrace with [Homebrew](https://brew.sh/):

```shell
brew install openfasttrace
```

The formula installs the OpenJDK 17 runtime dependency and provides the `oft` command. For example:

```shell
oft trace /path/to/directory/being/traced
```
* [Installation on Linux](doc/user_guide/installation/linux.md)
* [Installation on macOS](doc/user_guide/installation/macos.md)
* [Installation on Windows](doc/user_guide/installation/windows.md)

## Running OpenFastTrace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public boolean hasNoDefects()
*
* @return all defect items found during tracing.
*/
@SuppressWarnings("java:S2384") // LinkedSpecificationItems are currently mutable intentionally.
public List<LinkedSpecificationItem> getDefectItems()
{
return this.defectItems;
Expand All @@ -44,6 +45,7 @@ public List<LinkedSpecificationItem> getDefectItems()
*
* @return all items found during tracing.
*/
@SuppressWarnings("java:S2384") // LinkedSpecificationItems are currently mutable intentionally.
public List<LinkedSpecificationItem> getItems()
{
return this.items;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Arrays.asList;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -88,17 +89,13 @@ private boolean validateTraceCommand()

private boolean validateConvertCommand()
{
boolean ok = false;
final String format = this.arguments.getOutputFormat();
if (format != null && !new ExporterFactoryLoader(null).isFormatSupported(format))
final String format = Objects.requireNonNull(this.arguments.getOutputFormat());
if (!new ExporterFactoryLoader(null).isFormatSupported(format))
{
this.error = "export format '" + format + "' is not supported.";
return false;
}
else
{
ok = true;
}
return ok;
return true;
}

private static String listCommands()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.itsallcode.openfasttrace.core.cli;

import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

Expand All @@ -12,6 +11,8 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;

@ExtendWith(MockitoExtension.class)
class TestArgumentValidator
{
Expand All @@ -35,22 +36,22 @@ void testNoCommandGivenIsInvalid()
@Test
void testTraceCommandGivenIsValid()
{
cliArgs.setUnnamedValues(asList("trace"));
cliArgs.setUnnamedValues(List.of("trace"));
assertValidatorResult("", "");
}

@Test
void testTraceCommandQuietAndNoOutputFileGivenIsValid()
{
cliArgs.setUnnamedValues(asList("trace"));
cliArgs.setUnnamedValues(List.of("trace"));
cliArgs.setV(ReportVerbosity.QUIET);
assertValidatorResult("", "");
}

@Test
void testTraceCommandQuietAndOutputFileGivenIsNotValid()
{
cliArgs.setUnnamedValues(asList("trace"));
cliArgs.setUnnamedValues(List.of("trace"));
cliArgs.setV(ReportVerbosity.QUIET);
cliArgs.setOutputFile("outputFile");
assertValidatorResult(
Expand All @@ -61,15 +62,15 @@ void testTraceCommandQuietAndOutputFileGivenIsNotValid()
@Test
void testConvertCommandGivenIsValid()
{
cliArgs.setUnnamedValues(asList("convert"));
cliArgs.setUnnamedValues(List.of("convert"));
cliArgs.setOutputFormat("unsupportedFormat");
assertValidatorResult("export format 'unsupportedFormat' is not supported.", "");
}

@Test
void testUnknownCommandGivenIsNotValid()
{
cliArgs.setUnnamedValues(asList("unknownCommand"));
cliArgs.setUnnamedValues(List.of("unknownCommand"));
assertValidatorResult("'unknownCommand' is not an OFT command.",
"Choose one of 'help','convert','trace'.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.*;
Expand All @@ -22,11 +21,14 @@ class ClassPathServiceLoaderTest
@Test
void loadingNonAccessibleServiceFails()
{
final ServiceOrigin origin = ServiceOrigin.forCurrentClassPath();
final ServiceConfigurationError error = assertThrows(ServiceConfigurationError.class,
() -> ClassPathServiceLoader.create(DummyService.class, origin));
assertThat(error.getMessage(), equalTo(
"org.itsallcode.openfasttrace.core.serviceloader.ClassPathServiceLoaderTest$DummyService: module org.itsallcode.openfasttrace.core does not declare `uses`"));
try (final ServiceOrigin origin = ServiceOrigin.forCurrentClassPath())
{
final ServiceConfigurationError error = assertThrows(ServiceConfigurationError.class,
() -> ClassPathServiceLoader.create(DummyService.class, origin));
assertThat(error.getMessage(), equalTo(
"org.itsallcode.openfasttrace.core.serviceloader.ClassPathServiceLoaderTest$DummyService:"
+ " module org.itsallcode.openfasttrace.core does not declare `uses`"));
}
}

@Test
Expand All @@ -46,25 +48,26 @@ void loadingReturnsService(@Mock final ServiceLoader<DummyService> serviceLoader
when(serviceLoaderMock.stream()).thenReturn(Stream.of(providerMock));
when(providerMock.get()).thenReturn(service);
when(originMock.getClassLoader()).thenReturn(DummyServiceImpl.class.getClassLoader());
final List<DummyService> services = new ClassPathServiceLoader<DummyService>(originMock, serviceLoaderMock)
final List<DummyService> services = new ClassPathServiceLoader<>(originMock, serviceLoaderMock)
.load().toList();
assertThat(services, contains(sameInstance(service)));
}

@Test
void loadingIgnoresServicesFromOtherClassLoaders(@Mock final ServiceLoader<DummyService> serviceLoaderMock,
@Mock final Provider<DummyService> providerMock, @Mock final ServiceOrigin originMock)
@Mock final Provider<DummyService> providerMock, @Mock final ServiceOrigin originMock,
@Mock ClassLoader classLoaderMock)
{
final DummyServiceImpl service = new DummyServiceImpl();
when(serviceLoaderMock.stream()).thenReturn(Stream.of(providerMock));
when(providerMock.get()).thenReturn(service);
when(originMock.getClassLoader()).thenReturn(mock(ClassLoader.class));
final List<DummyService> services = new ClassPathServiceLoader<DummyService>(originMock, serviceLoaderMock)
when(originMock.getClassLoader()).thenReturn(classLoaderMock);
final List<DummyService> services = new ClassPathServiceLoader<>(originMock, serviceLoaderMock)
.load().toList();
assertThat(services, empty());
}

static interface DummyService
interface DummyService
{
}

Expand Down
2 changes: 1 addition & 1 deletion doc/_config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
title: OpenFastTrace
description: Requirement tracing suite for Agile Development
description: Requirement management and tracing suite

remote_theme: just-the-docs/just-the-docs

Expand Down
Loading