vault backup: 2026-07-16 03:52:12
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# List of contents
|
||||
1. [[#REST API with Spring]]
|
||||
2. [[#Flask API in Python]]
|
||||
3. [[#DOCKER]]
|
||||
4. [[#gRPC]]
|
||||
5.
|
||||
3. [[#gRPC]]
|
||||
4. [[#JUnit]]
|
||||
5. [[#EasyMock]]
|
||||
6. [[#DOCKER]]
|
||||
|
||||
<div class="page-break"></div>
|
||||
|
||||
@@ -450,48 +451,6 @@ for x, y in thisdict.items(): # Looping over key-value pairs as tuples
|
||||
| setdefault() | Returns the value of the specified key. If the key does not exist: insert the key, with the specified value |
|
||||
| update() | Updates the dictionary with the specified key-value pairs |
|
||||
| values() | Returns a list of all the values in the dictionary |
|
||||
<div class="page-break"></div>
|
||||
# DOCKER
|
||||
|
||||
**Docker reference: https://docs.docker.com/**
|
||||
|
||||
### Dockerfiles
|
||||
https://docs.docker.com/get-started/docker-concepts/building-images/writing-a-dockerfile/
|
||||
https://docs.docker.com/reference/dockerfile/
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.13
|
||||
WORKDIR /usr/local/app
|
||||
|
||||
# Install the application dependencies
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy in the source code
|
||||
COPY src ./src
|
||||
EXPOSE 8080
|
||||
|
||||
# Setup an app user so the container doesn't run as the root user
|
||||
RUN useradd app
|
||||
USER app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
|
||||
```
|
||||
|
||||
### Building docker
|
||||
|
||||
```bash
|
||||
docker build -t <tag>
|
||||
```
|
||||
|
||||
### Docker processes
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
#### Exercises
|
||||
- [L09P01 - Registry Office Service Deployment](file:///home/nikola/Documents/EIST/eist26l09p01-go38coz)
|
||||
- [L09P02 - Garching Best Software](file:///home/nikola/Documents/EIST/eist26l09p02-go38coz)
|
||||
- [L08PE04 - Spaceship](file:///home/nikola/Documents/EIST/eist26l0pe04-go38coz)
|
||||
|
||||
<div class="page-break"></div>
|
||||
|
||||
@@ -768,7 +727,162 @@ public String displayPlaylist(int[] playlist) throws SpotifyClientException {
|
||||
- L02PB01 Weather Reporter
|
||||
- L02P01 Spotify gRPC
|
||||
- L03PE03 Gobblemaps
|
||||
# JUnit
|
||||
|
||||
## assertThrows()
|
||||
```java
|
||||
@Test
|
||||
public void testSetOnlineCourseUrlWithInvalidUrl() {
|
||||
OnlineCourse course = new OnlineCourse("test");
|
||||
// You need to pass the CLASS of the exception and a runnable which calls the function
|
||||
// then the test will pass if EXACTLY this exception is throwed
|
||||
// If you want to test for any exception pass Exception.class however, that is usually discouraged and not needed
|
||||
assertThrows(MalformedURLException.class,() -> course.setUrl("hjdahjsd"));
|
||||
}
|
||||
```
|
||||
## assertDoesNotThrow()
|
||||
```java
|
||||
@Test
|
||||
public void testSetOnlineCourseUrlWithValidUrl(){
|
||||
OnlineCourse course = new OnlineCourse("test");
|
||||
// Simply assertDoesNotThrow with a runnable
|
||||
assertDoesNotThrow(() -> course.setUrl("https://test"));
|
||||
|
||||
// We need to handle constructor of URL throwing an exception despite knowing that it won't as we are passing it a correct URL
|
||||
try {
|
||||
assertEquals(new URL("https://test"),course.getUrl());
|
||||
} catch (MalformedURLException e) {
|
||||
}
|
||||
}
|
||||
```
|
||||
# EasyMock
|
||||
|
||||
`@TestSubject` annotations automatically calls the constructor with the mockObjects. However it is not applicable for constructors with other parameters that are not mocked(for example primitive types). In such cases you can call the constructor of the **test subject** as usual inside the test or in a @Before method or wherever you want.
|
||||
|
||||
**Second example contains how to expect *void* method calls**
|
||||
## Example with TestSubject
|
||||
|
||||
```java
|
||||
// Needs to extend the tests with EasyMock
|
||||
@ExtendWith(EasyMockExtension.class)
|
||||
class DiscussionTest {
|
||||
|
||||
// TestSubject annotations automatically calls the constructor with the mockObjects
|
||||
// However it is not applicable for constructors with other parameters
|
||||
|
||||
@TestSubject
|
||||
private Discussion discussion;
|
||||
|
||||
|
||||
// Mock objects need to be annotated with @Mock
|
||||
@Mock
|
||||
private Course courseMock;
|
||||
|
||||
@Mock
|
||||
private Comment commentMock;
|
||||
|
||||
// TODO implement the tests
|
||||
|
||||
@Test
|
||||
public void testComment() {
|
||||
// First we need to record
|
||||
// Expect a function call and set a predetermined return value
|
||||
// This expects the method to be called exactly once
|
||||
expect(commentMock.save()).andReturn(true);
|
||||
|
||||
// After setting all expectations we need to replay the mock - e.g set it so it behaves the way we recorded
|
||||
replay(commentMock);
|
||||
|
||||
// Test your objects as usual
|
||||
discussion = new Discussion();
|
||||
assertEquals(0,discussion.getNumberOfComments());
|
||||
assertTrue(discussion.addComment(commentMock));
|
||||
assertEquals(1,discussion.getNumberOfComments());
|
||||
|
||||
// At the end you need to verify the mock - this checks whether the expected methods were actually called
|
||||
verify(commentMock);
|
||||
}
|
||||
|
||||
// The methods below show the same usage
|
||||
@Test
|
||||
public void testCommentIfSavingFails() {
|
||||
expect(commentMock.save()).andReturn(false);
|
||||
replay(commentMock);
|
||||
|
||||
discussion = new Discussion();
|
||||
assertEquals(0,discussion.getNumberOfComments());
|
||||
assertFalse(discussion.addComment(commentMock));
|
||||
assertEquals(0,discussion.getNumberOfComments());
|
||||
|
||||
verify(commentMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartCourseDiscussion() {
|
||||
Person person = new Lecturer("","",LocalDate.now());
|
||||
String testTopic = "testTopic";
|
||||
|
||||
expect(courseMock.isDiscussionAllowed(person)).andReturn(true);
|
||||
|
||||
replay(courseMock);
|
||||
assertTrue(discussion.startCourseDiscussion(courseMock,person,testTopic));
|
||||
assertEquals(courseMock,discussion.getCourse());
|
||||
assertEquals(testTopic,discussion.getTopic());
|
||||
|
||||
verify(courseMock);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Example with custom Constructor (also contains expecting *void* call)
|
||||
|
||||
```java
|
||||
@Mock
|
||||
Platform platformMock;
|
||||
|
||||
...
|
||||
|
||||
@Test
|
||||
public void addNoteGetsURIFromPlatform() throws URISyntaxException {
|
||||
URI uri = URI.create("https://notes.tum.de/examplePath"); // An example uri your mock can return
|
||||
String expectedWriteDataPath = uri.getPath(); // The path that the NotesServer should write to
|
||||
|
||||
// Set the mock to expect the call and return the set URI
|
||||
expect(platformMock.nextURI()).andReturn(uri);
|
||||
|
||||
// To expect a void method call you can just call the method like usual before **replaying** the mock
|
||||
platformMock.writeData(expectedWriteDataPath,"Some text");
|
||||
|
||||
// Replay the mock
|
||||
replay(platformMock);
|
||||
|
||||
// Instead of annotating with @TestSubject we instantiate the testServer(System Under Test) inside the Test
|
||||
NotesServer testServer = new NotesServer(platformMock, false, false);
|
||||
|
||||
// Test like usual
|
||||
URI testUri = testServer.addNote("alice", "Some text");
|
||||
assertEquals(expectedWriteDataPath,testUri.getPath());
|
||||
|
||||
// At the end you need to verify the mock - this checks whether the expected methods were actually called
|
||||
verify(platformMock);
|
||||
}
|
||||
```
|
||||
|
||||
## If you want multiple method invocations
|
||||
|
||||
|
||||
| Method | Behaviour |
|
||||
| ---------------- | -------------------------------------------------------------------------------------- |
|
||||
| `.times(3)` | Expects the method to be called **exactly** 3 times. |
|
||||
| `.times(2,5)` | Expects the method to be called between **2 and 5** times (inclusive). |
|
||||
| `.atLeastOnce()` | Expects the method to be called **1 or more** times. |
|
||||
| `.anyTimes()` | The method can be called **0 or more** times (it will never cause `verify()` to fail). |
|
||||
For *void* methods:
|
||||
|
||||
```java
|
||||
commentMock.update(); // Call the void method
|
||||
expectLastCall().times(3); // Set the invocation count
|
||||
```
|
||||
<div class="page-break"></div>
|
||||
|
||||
## ALL RESOURCE LINKS:
|
||||
@@ -794,3 +908,48 @@ public String displayPlaylist(int[] playlist) throws SpotifyClientException {
|
||||
- **man pages (command line, not online)**
|
||||
|
||||
<div class="page-break"></div>
|
||||
|
||||
# DOCKER
|
||||
|
||||
**Docker reference: https://docs.docker.com/**
|
||||
|
||||
### Dockerfiles
|
||||
https://docs.docker.com/get-started/docker-concepts/building-images/writing-a-dockerfile/
|
||||
https://docs.docker.com/reference/dockerfile/
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.13
|
||||
WORKDIR /usr/local/app
|
||||
|
||||
# Install the application dependencies
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy in the source code
|
||||
COPY src ./src
|
||||
EXPOSE 8080
|
||||
|
||||
# Setup an app user so the container doesn't run as the root user
|
||||
RUN useradd app
|
||||
USER app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
|
||||
```
|
||||
|
||||
### Building docker
|
||||
|
||||
```bash
|
||||
docker build -t <tag>
|
||||
```
|
||||
|
||||
### Docker processes
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
#### Exercises
|
||||
- [L09P01 - Registry Office Service Deployment](file:///home/nikola/Documents/EIST/eist26l09p01-go38coz)
|
||||
- [L09P02 - Garching Best Software](file:///home/nikola/Documents/EIST/eist26l09p02-go38coz)
|
||||
- [L08PE04 - Spaceship](file:///home/nikola/Documents/EIST/eist26l0pe04-go38coz)
|
||||
|
||||
<div class="page-break"></div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user