From 0cf1fa2db96c6aeb7b64903a73420aa332fe3888 Mon Sep 17 00:00:00 2001 From: Ryan Wilson Date: Tue, 12 Dec 2023 23:15:01 -0500 Subject: [PATCH 1/3] Migrate fully to new test naming scheme --- Package.swift | 2 +- Tests/GoogleAITests/ChatTests.swift | 31 +------ .../failure-model-not-found.json} | 0 .../success-total-tokens.json} | 0 .../streaming-failure-malformed-content.txt} | 2 +- .../streaming-success-basic-reply-long.txt | 19 +++-- ...unary-success-missing-safety-ratings.json} | 0 .../GoogleAITests/GenerativeModelTests.swift | 84 +++++++------------ .../ExampleStreamingResponse.json | 45 ---------- 9 files changed, 46 insertions(+), 137 deletions(-) rename Tests/GoogleAITests/{SampleResponses/CountTokensModelNotFound.json => CountTokenResponses/failure-model-not-found.json} (100%) rename Tests/GoogleAITests/{SampleResponses/CountTokensResponse.json => CountTokenResponses/success-total-tokens.json} (100%) rename Tests/GoogleAITests/{SampleResponses/MalformedContentStreamingResponse.json => GenerateContentResponses/streaming-failure-malformed-content.txt} (93%) rename Tests/GoogleAITests/{SampleResponses/MissingSafetyRatings.json => GenerateContentResponses/unary-success-missing-safety-ratings.json} (100%) delete mode 100644 Tests/GoogleAITests/SampleResponses/ExampleStreamingResponse.json diff --git a/Package.swift b/Package.swift index 5245178..79e8173 100644 --- a/Package.swift +++ b/Package.swift @@ -43,8 +43,8 @@ let package = Package( dependencies: ["GoogleGenerativeAI"], path: "Tests", resources: [ + .process("GoogleAITests/CountTokenResponses"), .process("GoogleAITests/GenerateContentResponses"), - .process("GoogleAITests/SampleResponses"), ] ), ] diff --git a/Tests/GoogleAITests/ChatTests.swift b/Tests/GoogleAITests/ChatTests.swift index 8c8a3a8..4020d4b 100644 --- a/Tests/GoogleAITests/ChatTests.swift +++ b/Tests/GoogleAITests/ChatTests.swift @@ -32,8 +32,8 @@ final class ChatTests: XCTestCase { func testMergingText() async throws { let fileURL = try XCTUnwrap(Bundle.module.url( - forResource: "ExampleStreamingResponse", - withExtension: "json" + forResource: "streaming-success-basic-reply-long", + withExtension: "txt" )) MockURLProtocol.requestHandler = { request in @@ -59,32 +59,7 @@ final class ChatTests: XCTestCase { XCTAssertEqual(chat.history.count, 2) XCTAssertEqual(chat.history[0].parts[0].text, input) - let finalText = """ - As an AI language model, I am designed to help you with a wide range of topics and \ - questions. Here are some examples of the types of questions you can ask me: - - **General knowledge:** Ask me about a variety of topics, including history, science, \ - technology, art, culture, and more. - - **Creative writing:** Request me to write a story, poem, or any other creative piece \ - based on your specifications. - - **Language translation:** I can translate text from one language to another. - - **Math problems:** I can solve math equations and provide step-by-step solutions. - - **Trivia and quizzes:** Test your knowledge by asking me trivia questions or creating \ - quizzes on various subjects. - - **Conversation:** Engage in casual conversation on any topic of your interest. - - **Advice and suggestions:** Seek advice on various matters, such as relationships, \ - career choices, or personal growth. - - **Entertainment:** Request jokes, riddles, or fun facts to lighten up your day. - - **Code generation:** Ask me to write code snippets in different programming languages. - - **Real-time information:** Inquire about current events, weather conditions, or other \ - up-to-date information. - - **Creative ideas:** Generate creative ideas for projects, hobbies, or any other endeavor. - - **Health and wellness:** Get information about health, fitness, and nutrition. - - **Travel and geography:** Ask about places, landmarks, cultures, and travel tips. - - Remember that my responses are based on the information available to me up until my \ - training cutoff date in September 2021. For the most up-to-date information, especially \ - on rapidly changing topics, it's always a good idea to consult reliable and recent sources. - """ + let finalText = "1 2 3 4 5 6 7 8 9 10" let assembledExpectation = ModelContent(role: "model", parts: finalText) XCTAssertEqual(chat.history[0].parts[0].text, input) XCTAssertEqual(chat.history[1], assembledExpectation) diff --git a/Tests/GoogleAITests/SampleResponses/CountTokensModelNotFound.json b/Tests/GoogleAITests/CountTokenResponses/failure-model-not-found.json similarity index 100% rename from Tests/GoogleAITests/SampleResponses/CountTokensModelNotFound.json rename to Tests/GoogleAITests/CountTokenResponses/failure-model-not-found.json diff --git a/Tests/GoogleAITests/SampleResponses/CountTokensResponse.json b/Tests/GoogleAITests/CountTokenResponses/success-total-tokens.json similarity index 100% rename from Tests/GoogleAITests/SampleResponses/CountTokensResponse.json rename to Tests/GoogleAITests/CountTokenResponses/success-total-tokens.json diff --git a/Tests/GoogleAITests/SampleResponses/MalformedContentStreamingResponse.json b/Tests/GoogleAITests/GenerateContentResponses/streaming-failure-malformed-content.txt similarity index 93% rename from Tests/GoogleAITests/SampleResponses/MalformedContentStreamingResponse.json rename to Tests/GoogleAITests/GenerateContentResponses/streaming-failure-malformed-content.txt index 95b35e7..273b6cd 100644 --- a/Tests/GoogleAITests/SampleResponses/MalformedContentStreamingResponse.json +++ b/Tests/GoogleAITests/GenerateContentResponses/streaming-failure-malformed-content.txt @@ -1 +1 @@ -data: {"candidates": [{"content": {"invalid-field": true},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} +data: {"candidates": [{"content": {"missing-parts": true},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} diff --git a/Tests/GoogleAITests/GenerateContentResponses/streaming-success-basic-reply-long.txt b/Tests/GoogleAITests/GenerateContentResponses/streaming-success-basic-reply-long.txt index fe662e6..bca9514 100644 --- a/Tests/GoogleAITests/GenerateContentResponses/streaming-success-basic-reply-long.txt +++ b/Tests/GoogleAITests/GenerateContentResponses/streaming-success-basic-reply-long.txt @@ -1,12 +1,19 @@ -data: {"candidates": [{"content": {"parts": [{"text": "**Cats:**\n\n- **Physical Characteristics:**\n - Size: Cats come"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} +data: {"candidates": [{"content": {"parts": [{"text": "1 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} -data: {"candidates": [{"content": {"parts": [{"text": " in a wide range of sizes, from small breeds like the Singapura to large breeds like the Maine Coon.\n - Fur: Cats have soft, furry coats"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "2 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} -data: {"candidates": [{"content": {"parts": [{"text": " that can vary in length and texture depending on the breed.\n - Eyes: Cats have large, expressive eyes that can be various colors, including green, blue, yellow, and hazel.\n - Ears: Cats have pointed, erect ears that are sensitive to sound.\n - Tail: Cats have long"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "3 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} -data: {"candidates": [{"content": {"parts": [{"text": ", flexible tails that they use for balance and communication.\n\n- **Behavior and Personality:**\n - Independent: Cats are often described as independent animals that enjoy spending time alone.\n - Affectionate: Despite their independent nature, cats can be very affectionate and form strong bonds with their owners.\n - Playful: Cats are naturally playful and enjoy engaging in activities such as chasing toys, climbing, and pouncing.\n - Curious: Cats are curious creatures that love to explore their surroundings.\n - Vocal: Cats communicate through a variety of vocalizations, including meows, purrs, hisses, and grow"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "4 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} -data: {"candidates": [{"content": {"parts": [{"text": "ls.\n\n- **Health and Care:**\n - Diet: Cats are obligate carnivores, meaning they require animal-based protein for optimal health.\n - Grooming: Cats spend a significant amount of time grooming themselves to keep their fur clean and free of mats.\n - Exercise: Cats need regular exercise to stay healthy and active. This can be achieved through play sessions or access to outdoor space.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a cat's health and detecting any potential health issues early on.\n\n**Dogs:**\n\n- **Physical Characteristics:**\n - Size: Dogs come in a wide range of sizes, from small breeds like the Chihuahua to giant breeds like the Great Dane.\n - Fur: Dogs have fur coats that can vary in length, texture, and color depending on the breed.\n - Eyes: Dogs have expressive eyes that can be various colors, including brown, blue, green, and hazel.\n - Ears: Dogs have floppy or erect ears that are sensitive to sound.\n - Tail: Dogs have long, wagging tails that they use for communication and expressing emotions.\n\n- **Behavior and Personality:**\n - Loyal: Dogs are known for their loyalty and"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "5 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} -data: {"candidates": [{"content": {"parts": [{"text": " devotion to their owners.\n - Friendly: Dogs are generally friendly and outgoing animals that enjoy interacting with people and other animals.\n - Playful: Dogs are playful and energetic creatures that love to engage in activities such as fetching, running, and playing with toys.\n - Trainable: Dogs are highly trainable and can learn a variety of commands and tricks.\n - Vocal: Dogs communicate through a variety of vocalizations, including barking, howling, whining, and growling.\n\n- **Health and Care:**\n - Diet: Dogs are omnivores and can eat a variety of foods, including meat, vegetables, and grains.\n - Grooming: Dogs require regular grooming to keep their fur clean and free of mats. The frequency of grooming depends on the breed and coat type.\n - Exercise: Dogs need regular exercise to stay healthy and active. The amount of exercise required varies depending on the breed and age of the dog.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a dog's health and detecting any potential health issues early on."}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "6 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} +data: {"candidates": [{"content": {"parts": [{"text": "7 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": "8 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": "9 "}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": "10"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} diff --git a/Tests/GoogleAITests/SampleResponses/MissingSafetyRatings.json b/Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json similarity index 100% rename from Tests/GoogleAITests/SampleResponses/MissingSafetyRatings.json rename to Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json diff --git a/Tests/GoogleAITests/GenerativeModelTests.swift b/Tests/GoogleAITests/GenerativeModelTests.swift index 3dc36e2..e00a1c5 100644 --- a/Tests/GoogleAITests/GenerativeModelTests.swift +++ b/Tests/GoogleAITests/GenerativeModelTests.swift @@ -147,21 +147,6 @@ final class GenerativeModelTests: XCTestCase { // TODO: Add assertions } - private func internalTestGenerateContent(resource: String, - safetyRatingsCount: Int = 6) async throws { - MockURLProtocol.requestHandler = try httpRequestHandler( - forResource: resource, - withExtension: "json" - ) - - let content = try await model.generateContent("What sorts of questions can I ask you?") - - // TODO: Add assertions for response content - let promptFeedback = try XCTUnwrap(content.promptFeedback) - XCTAssertEqual(promptFeedback.safetyRatings.count, safetyRatingsCount) - XCTAssertNotNil(content.text) - } - func testGenerateContent_failure_invalidAPIKey() async throws { let expectedStatusCode = 400 MockURLProtocol @@ -400,7 +385,15 @@ final class GenerativeModelTests: XCTestCase { } func testGenerateContentMissingSafetyRatings() async throws { - try await internalTestGenerateContent(resource: "MissingSafetyRatings", safetyRatingsCount: 0) + MockURLProtocol.requestHandler = try httpRequestHandler( + forResource: "unary-success-missing-safety-ratings", + withExtension: "json" + ) + + let content = try await model.generateContent(testPrompt) + let promptFeedback = try XCTUnwrap(content.promptFeedback) + XCTAssertEqual(promptFeedback.safetyRatings.count, 0) + XCTAssertNotNil(content.text) } // MARK: - Generate Content (Streaming) @@ -499,7 +492,7 @@ final class GenerativeModelTests: XCTestCase { responses += 1 } - XCTAssertEqual(responses, 6) + XCTAssertEqual(responses, 10) } func testGenerateContentStream_successBasicReplyShort() async throws { @@ -632,75 +625,54 @@ final class GenerativeModelTests: XCTestCase { func testGenerateContentStream_malformedContent() async throws { MockURLProtocol .requestHandler = try httpRequestHandler( - forResource: "MalformedContentStreamingResponse", - withExtension: "json" + forResource: "streaming-failure-malformed-content", + withExtension: "txt" ) let stream = model.generateContentStream(testPrompt) - var responseError: Error? do { for try await content in stream { XCTFail("Unexpected content in stream: \(content)") } - } catch { - responseError = error - } + } catch let GenerateContentError.internalError(underlyingError as InvalidCandidateError) { + guard case let .malformedContent(contentError) = underlyingError else { + XCTFail("Not a malformed content error: \(underlyingError)") + return + } - XCTAssertNotNil(responseError) - let generateContentError = try XCTUnwrap(responseError as? GenerateContentError) - guard case let .internalError(underlyingError) = generateContentError else { - XCTFail("Not an internal error: \(generateContentError)") - return - } - let invalidCandidateError = try XCTUnwrap(underlyingError as? InvalidCandidateError) - guard case let .malformedContent(malformedContentUnderlyingError) = invalidCandidateError else { - XCTFail("Not a malformed content error: \(invalidCandidateError)") + XCTAssert(contentError is DecodingError) return } - _ = try XCTUnwrap( - malformedContentUnderlyingError as? DecodingError, - "Not a decoding error: \(malformedContentUnderlyingError)" - ) + + XCTFail("Expected an internal decoding error.") } // MARK: - Count Tokens func testCountTokens_succeeds() async throws { MockURLProtocol.requestHandler = try httpRequestHandler( - forResource: "CountTokensResponse", + forResource: "success-total-tokens", withExtension: "json" ) let response = try await model.countTokens("Why is the sky blue?") - XCTAssertEqual(response.totalTokens, 6) } func testCountTokens_modelNotFound() async throws { MockURLProtocol.requestHandler = try httpRequestHandler( - forResource: "CountTokensModelNotFound", withExtension: "json", + forResource: "failure-model-not-found", withExtension: "json", statusCode: 404 ) - var response: CountTokensResponse? - var responseError: Error? do { - response = try await model.countTokens("Why is the sky blue?") - } catch { - responseError = error - } - - XCTAssertNil(response) - XCTAssertNotNil(responseError) - let countTokensError = try XCTUnwrap(responseError as? CountTokensError) - guard case let .internalError(underlyingError) = countTokensError else { - XCTFail("Not an internal error: \(countTokensError)") - return + _ = try await model.countTokens("Why is the sky blue?") + XCTFail("Request should not have succeeded.") + } catch let CountTokensError.internalError(rpcError as RPCError) { + XCTAssertEqual(rpcError.httpResponseCode, 404) + XCTAssertEqual(rpcError.status, .notFound) + XCTAssert(rpcError.message.hasPrefix("models/test-model-name is not found")) } - let rpcError = try XCTUnwrap(underlyingError as? RPCError) - XCTAssertEqual(rpcError.httpResponseCode, 404) - XCTAssertEqual(rpcError.status, .notFound) - XCTAssert(rpcError.message.hasPrefix("models/test-model-name is not found")) } // MARK: - Helpers diff --git a/Tests/GoogleAITests/SampleResponses/ExampleStreamingResponse.json b/Tests/GoogleAITests/SampleResponses/ExampleStreamingResponse.json deleted file mode 100644 index 48b054e..0000000 --- a/Tests/GoogleAITests/SampleResponses/ExampleStreamingResponse.json +++ /dev/null @@ -1,45 +0,0 @@ -data: {"candidates": [{"content": {"parts": [{"text": " As an AI language model, I am designed to help you with a wide range"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} - -data: {"candidates": [{"content": {"parts": [{"text": " of topics and questions. Here are some examples of the types of questions you can"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " ask me:\n- **General knowledge:** Ask me about a variety of topics"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": ", including history, science, technology, art, culture, and more.\n"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": "- **Creative writing:** Request me to write a story, poem, or any"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " other creative piece based on your specifications.\n- **Language translation:** I can"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " translate text from one language to another.\n- **Math problems:** I can"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " solve math equations and provide step-by-step solutions.\n- **Trivia"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " and quizzes:** Test your knowledge by asking me trivia questions or creating quizzes on various"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " subjects.\n- **Conversation:** Engage in casual conversation on any topic of your"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " interest.\n- **Advice and suggestions:** Seek advice on various matters, such"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " as relationships, career choices, or personal growth.\n- **Entertainment:** Request"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " jokes, riddles, or fun facts to lighten up your day.\n- **"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": "Code generation:** Ask me to write code snippets in different programming languages.\n-"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " **Real-time information:** Inquire about current events, weather conditions, or"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " other up-to-date information.\n- **Creative ideas:** Generate creative"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " ideas for projects, hobbies, or any other endeavor.\n- **Health and"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " wellness:** Get information about health, fitness, and nutrition.\n- **Travel"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " and geography:** Ask about places, landmarks, cultures, and travel tips.\n\n"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": "Remember that my responses are based on the information available to me up until my training"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " cutoff date in September 2021. For the most up-to"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": "-date information, especially on rapidly changing topics, it's always a good"}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} - -data: {"candidates": [{"content": {"parts": [{"text": " idea to consult reliable and recent sources."}]},"index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_TOXICITY","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_VIOLENCE","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} From 1b0d8fcafac725b48d9dda1735db40b21e5e461e Mon Sep 17 00:00:00 2001 From: Ryan Wilson Date: Tue, 12 Dec 2023 23:19:28 -0500 Subject: [PATCH 2/3] Add failure if the test case falls through --- Tests/GoogleAITests/GenerativeModelTests.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/GoogleAITests/GenerativeModelTests.swift b/Tests/GoogleAITests/GenerativeModelTests.swift index e00a1c5..ada3f6e 100644 --- a/Tests/GoogleAITests/GenerativeModelTests.swift +++ b/Tests/GoogleAITests/GenerativeModelTests.swift @@ -672,7 +672,10 @@ final class GenerativeModelTests: XCTestCase { XCTAssertEqual(rpcError.httpResponseCode, 404) XCTAssertEqual(rpcError.status, .notFound) XCTAssert(rpcError.message.hasPrefix("models/test-model-name is not found")) + return } + + XCTFail("Expected internal RPCError.") } // MARK: - Helpers From 90be0f0bdda6455f51beeb638e2c33f31a35e93d Mon Sep 17 00:00:00 2001 From: Ryan Wilson Date: Tue, 12 Dec 2023 23:37:12 -0500 Subject: [PATCH 3/3] Check text value, shorten response --- .../unary-success-missing-safety-ratings.json | 2 +- Tests/GoogleAITests/GenerativeModelTests.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json b/Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json index 9e7ff8d..645d3e6 100644 --- a/Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json +++ b/Tests/GoogleAITests/GenerateContentResponses/unary-success-missing-safety-ratings.json @@ -4,7 +4,7 @@ "content": { "parts": [ { - "text": "The sky is blue because of a phenomenon called Rayleigh scattering. This refers to the scattering of light by particles that are smaller than the wavelength of light. In the case of the sky, the particles that are doing the scattering are molecules of nitrogen and oxygen.\n\nWhen sunlight hits these molecules, the shorter wavelengths of light (blue and violet) are scattered more than the longer wavelengths (red and orange). This is because the shorter wavelengths have a higher energy and are therefore more likely to interact with the molecules.\n\nThe scattered blue light is then redirected in all directions, which is why we see the sky as being blue. The amount of scattering depends on the wavelength of light and the size of the particles, which is why the sky appears to be a darker shade of blue when the sun is low in the sky (when the sunlight has to travel through more of the atmosphere to reach our eyes) and a lighter shade of blue when the sun is high in the sky (when the sunlight has to travel through less of the atmosphere to reach our eyes).\n\nIt is important to note that the sky is not actually blue. It only appears to be blue because of the way that light is scattered by the molecules in the atmosphere. If you were to travel to space, you would see that the sky is actually black." + "text": "This is the generated content." } ] }, diff --git a/Tests/GoogleAITests/GenerativeModelTests.swift b/Tests/GoogleAITests/GenerativeModelTests.swift index ada3f6e..ac0d946 100644 --- a/Tests/GoogleAITests/GenerativeModelTests.swift +++ b/Tests/GoogleAITests/GenerativeModelTests.swift @@ -393,7 +393,7 @@ final class GenerativeModelTests: XCTestCase { let content = try await model.generateContent(testPrompt) let promptFeedback = try XCTUnwrap(content.promptFeedback) XCTAssertEqual(promptFeedback.safetyRatings.count, 0) - XCTAssertNotNil(content.text) + XCTAssertEqual(content.text, "This is the generated content.") } // MARK: - Generate Content (Streaming)