<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hyunjin Shin (Jin)</title>
    <description>The latest articles on DEV Community by Hyunjin Shin (Jin) (@jinger-ale).</description>
    <link>https://dev.to/jinger-ale</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2032558%2F5eee7c85-b5a6-4544-a61f-dfc0494718a3.jpg</url>
      <title>DEV Community: Hyunjin Shin (Jin)</title>
      <link>https://dev.to/jinger-ale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jinger-ale"/>
    <language>en</language>
    <item>
      <title>Project Chronicles - Release 0.4 - Final</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Tue, 10 Dec 2024 01:48:38 +0000</pubDate>
      <link>https://dev.to/jinger-ale/project-chronicles-release-04-final-31b0</link>
      <guid>https://dev.to/jinger-ale/project-chronicles-release-04-final-31b0</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Issue : &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/626" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/issues/626&lt;/a&gt;&lt;br&gt;
Pull Request : &lt;a href="https://github.com/tarasglek/chatcraft.org/pull/759" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/pull/759&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This post continues the &lt;a href="https://dev.to/jinger-ale/project-chronicles-release-04-part-2-330a"&gt;blog post&lt;/a&gt; about Project Release 0.4&lt;/p&gt;

&lt;h2&gt;
  
  
  Progress
&lt;/h2&gt;

&lt;p&gt;I finialized my design and applied it. It looks like the following screenshots&lt;/p&gt;

&lt;h3&gt;
  
  
  ModelsSettings Page after change on Desktop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qhc72c7t06w8t128n9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qhc72c7t06w8t128n9e.png" alt="Image description" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Newly Added DataControls Page on Desktop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v74u3we8et0j3ralcku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v74u3we8et0j3ralcku.png" alt="Image description" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ModelsSettings Page after change on Mobile Device(iPhone 15 Pro)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbybccbc8jvioxxj2a786.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbybccbc8jvioxxj2a786.PNG" alt="Image description" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Newly Added DataControls Page on Mobile Device(iPhone 15 Pro)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1j7kpu1972jobggv7j4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1j7kpu1972jobggv7j4.PNG" alt="Image description" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;For this project, I mostly worked on Chatcraft. I think this project is really helpful to learn and understand &lt;code&gt;React&lt;/code&gt; and how to utilize AI API. If I am being honest, I didn't go out of my comfort zone as much as I could, compared to other fellow stdudents. They made really awesome contributions to a really large project such as mattermost and hugginface. However, compared to what I was at the begining of this semester, I am a totally different person as a developer. I got confidence. &lt;/p&gt;

&lt;p&gt;The true scope of the programming world and the level of skills required in the industry have always been unclear to me. I could never quite see where I stood or how far I needed to go. &lt;/p&gt;

&lt;p&gt;There's a significant difference between knowing your goals and blindly pushing forward without direction. Through this project and course, however, I’ve gained a clearer understanding of my objective position and the actual standards demanded in the field.&lt;/p&gt;

&lt;p&gt;This newfound clarity has helped to ease some of the vague anxieties I carried. While recognizing the immense heights of the programming world and realizing how far I still have to climb is somewhat furstrating, it has also provided me with a tangible sense of direction. Knowing the gap between where I am and where I need to be has given me a clearer vision and renewed determination.&lt;/p&gt;

&lt;p&gt;I am trying to and will keep trying to believe, although I am often swayed by my anxiety and concerns that I may never be able to become a developer, that I can do this and that I can become a developer if I keep going without giving up.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Project Chronicles - Release 0.4 - part 2</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 29 Nov 2024 06:52:15 +0000</pubDate>
      <link>https://dev.to/jinger-ale/project-chronicles-release-04-part-2-330a</link>
      <guid>https://dev.to/jinger-ale/project-chronicles-release-04-part-2-330a</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Issue : &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/626" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/issues/626&lt;/a&gt;&lt;br&gt;
Pull Request : &lt;a href="https://github.com/tarasglek/chatcraft.org/pull/759" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/pull/759&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This post continues the &lt;a href="https://dev.to/jinger-ale/project-chronicles-release-04-58g8"&gt;blog post&lt;/a&gt; about Project Release 0.4&lt;/p&gt;

&lt;h2&gt;
  
  
  Progress
&lt;/h2&gt;

&lt;p&gt;I started to write codes for this issue. Since a lot of changes were needed to be changed in codes, I tried my best to follow the original code style. Especially when I am changing CSS; I spent quite a bit of time on making my new code as similar to original codes as I can, and also I tried to make as less changes in code.&lt;/p&gt;

&lt;p&gt;The second thing that was challenging was the design. I've never thought I have a good sense of aesthetics, so I had no idea of what the desgin for the new page should look like. Moreover, in the issue there was no specific guide about what kind of design the maintainers want. It was good in a sense that I have a freedom to make it in my style and apply my creativity. However, it was also a bit confusing.&lt;br&gt;
So I went to the ChatGPT, looked at the settings page, and refered to that design.&lt;/p&gt;

&lt;h3&gt;
  
  
  ChatGPT Settings page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p06agnbx00wp8pbiesk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p06agnbx00wp8pbiesk.png" alt="Image description" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The third thing that I think about was the namings of the page. I considered among "Data", "Storage", "Data Controls", and "Database". Then, since the most popular and most used AI Chat is ChatGPT, I thought that if we follow the naming styles, it would be beneficial to users and less confusing to the users.&lt;/p&gt;

&lt;p&gt;The last thing that I considered was extra fix. There was duplicate declarations of interface; however, this wasn't directly related to the issue. So, I wasn't sure that if I should fix this or make a new issue for this. This was a really easy and simple problem, I thought that there was no need to open a new issue for this. So I just fixed it(removed one of them).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rko19j0g9i74n4wn9ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rko19j0g9i74n4wn9ju.png" alt="Image description" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Project Chronicles - Release 0.4</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 29 Nov 2024 06:20:33 +0000</pubDate>
      <link>https://dev.to/jinger-ale/project-chronicles-release-04-58g8</link>
      <guid>https://dev.to/jinger-ale/project-chronicles-release-04-58g8</guid>
      <description>&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This post is about a Project-release 0.4 for OSD600 course at Seneca College. For release 0.4, the students were required to push themselves further into Open Source Development World out of our comfort zone. I decided to work on a bit more complex issues on the &lt;code&gt;Chatcraft&lt;/code&gt; project. Then, I found an &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/626" rel="noopener noreferrer"&gt;issue&lt;/a&gt; that looked interesting and more difficult than the ones that I worked on before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progress
&lt;/h2&gt;

&lt;p&gt;Since this issue requires moving a substantial amount of code in a page(or component) into another, I first needed to fully understand the code inside the page, which is &lt;code&gt;ModelsSetting.tsx&lt;/code&gt;. Especially, I needed to understand the specific part that I am supposed to move. It was &lt;code&gt;persist&lt;/code&gt; option, &lt;code&gt;import&lt;/code&gt; option, and &lt;code&gt;export&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;I first started to study &lt;code&gt;persist&lt;/code&gt; option. It uses &lt;a href="https://dexie.org/" rel="noopener noreferrer"&gt;Dexie&lt;/a&gt; library. What it does is using indexed DB feature of browser. It stores data in indexedDB on browser, and some browsers can make it persist.&lt;/p&gt;

&lt;p&gt;This part confused me a lot. At first, I understood &lt;code&gt;persist&lt;/code&gt; option as something like even after I close the tab or window, the data is not deleted and when I open Chatcraft later, I can still retrieve the chat histroy. However, &lt;code&gt;persist&lt;/code&gt; here doesn't mean that. Whether the &lt;code&gt;persist&lt;/code&gt; option is turned on or not, the chat data is stored in IndexedDB. However, sometimes browsers delete the indexed data when it has not enough space or for some other reasons. &lt;code&gt;persist&lt;/code&gt; here means preventing the browser from deleting the indexed data arbitrarily. &lt;/p&gt;

&lt;p&gt;After I understand what &lt;code&gt;persist&lt;/code&gt; option means, I encountered the second problem. Some of the browsers didn't work for &lt;code&gt;persist&lt;/code&gt; option such as Safari. The option didn't work at all. On Chrome, it worked sometimes, but it didn't work for some other times. I researched about it, and then find out that it depends on the browser's behavior and decision. For example, the following factors can affect the availability of &lt;code&gt;persist&lt;/code&gt; option of Indexed DB.&lt;/p&gt;

&lt;p&gt;Reasons for Inconsistent Behavior of navigator.storage.persist() in Chrome are as follows: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User Interaction Requirement:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Chrome to grant persistent storage, it usually requires a user gesture (e.g., a click or a form submission). If the persist() method is called outside of such a gesture, Chrome might reject the request.&lt;br&gt;
For example, if you call navigator.storage.persist() inside a background task or an event that wasn't directly triggered by the user, Chrome may not grant the storage permission.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engagement and Usage Frequency:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chrome may also base its decision on how frequently the user interacts with your app. For apps that the user doesn't interact with often, Chrome may decide not to grant persistent storage.&lt;br&gt;
Frequent user interaction (like daily usage) or installing your app as a PWA can improve your app’s chances of being granted persistent storage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PWA Installation:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your app is installed as a Progressive Web App (PWA) or added to the user’s home screen, it has a higher chance of being granted persistent storage. Non-PWA websites might not be as likely to get persistent storage, especially if the user has not engaged much with your site.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quota and Storage Policies:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chrome, like other browsers, has a quota management system to ensure that a site doesn’t take up too much local storage. Even if you request persistent storage, Chrome might deny it if the site has exceeded its storage limits or if the system is running low on space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Device-Specific Factors:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On some devices, particularly mobile or low-storage devices, Chrome may be more conservative about granting persistent storage to avoid using too much disk space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser Updates and Features:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chrome might change how it handles persistent storage with new versions, and certain flags or experimental features could also affect the availability of navigator.storage.persist(). Occasionally, new browser features or settings might temporarily disable or restrict storage persistence.&lt;/p&gt;

&lt;p&gt;In the next post, I write about implementing the solution.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OSD600 - Lab09</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 22 Nov 2024 18:55:21 +0000</pubDate>
      <link>https://dev.to/jinger-ale/osd600-lab09-1d6a</link>
      <guid>https://dev.to/jinger-ale/osd600-lab09-1d6a</guid>
      <description>&lt;p&gt;Link to &lt;a href="https://pypi.org/project/code-mage/" rel="noopener noreferrer"&gt;the package&lt;/a&gt; that I released&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;This post is about lab 09 for OSD600 course at Seneca College. This week, we learned how to package our project and release it to public.  And also we learned about &lt;code&gt;git tag&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection
&lt;/h3&gt;

&lt;h4&gt;
  
  
  - Q1. Which release tool and package registry did you choose? Provide links to everything you mention.
&lt;/h4&gt;

&lt;p&gt;I used &lt;a href="https://python-poetry.org/" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt;. In the first week, I started my project without package manager. Since it was my first python project, I didn't know that python has package managers. Then, I learned that there is package manager similar to &lt;code&gt;npm&lt;/code&gt;, and recreated my project. This package manager also provides a way to release the project easily.&lt;br&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  - Q2. What was the process for creating a release? Be detailed so that other developers could read your blog and get some idea how to do the same.
&lt;/h4&gt;

&lt;p&gt;Step 1. Create PyPI account and generate api key for PyPI publish&lt;/p&gt;

&lt;p&gt;Step 2. Set up the API_KEY in &lt;code&gt;config.toml&lt;/code&gt; file for poetry.&lt;br&gt;
Poetry &lt;code&gt;config.toml&lt;/code&gt; for mac is located in &lt;code&gt;~/Library/Application Support/pypoetry&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[pypi]&lt;/span&gt;
&lt;span class="py"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"__token__"&lt;/span&gt;
&lt;span class="py"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pypi-&amp;lt;your-token&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you may need to set up the key as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry config pypi-token.pypi &amp;lt;your-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3. Build your poetry project in the root dir of your project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4. Run the following commend to publish it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  - Q3. What did you learn while doing your release? Did you have any "aha!" moments or get stuck?
&lt;/h4&gt;

&lt;p&gt;Poetry Package manager is so easy and kind that I didn't have a huge problem with publishing it. However, I had some problem using the tool that I published. I downloaded the tool with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;pip3 install code-mage
codemage test.js -s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of the features didn't work although it worked when I ran it from my project directory using &lt;code&gt;poetry run codemage&lt;/code&gt; command. I think when it builds the project for release, it mangles file structure or doesn't include some files. There was one function that reads version info from &lt;code&gt;pyproject.toml&lt;/code&gt; file. It correctly reads when I use it in project directory. However, it didn't work in my published version. So I had to change the logic.&lt;/p&gt;




&lt;h4&gt;
  
  
  - Q4. How much did you have to alter your code, files, build, etc. to use the chosen package format and registry?
&lt;/h4&gt;

&lt;p&gt;Fortunately, I started with package manager, I didn't have to change a lot. I only fixed some logics or some functions that only works in local environment(e.g. cloning the repo and running it).&lt;/p&gt;




&lt;h4&gt;
  
  
  - Q5. How did the User Testing session with your partner go? Describe what it was like, where they got stuck, and how you corrected the problems.
&lt;/h4&gt;

&lt;p&gt;I asked my seneca colleague. She was very confused by the Doc. She said it would be really tough or impossible to use the tool just by reading the Doc. I made a lot of changes in my Doc and made it as kind and easy as I can. I think I subconsciously assumed that they would know the steps that I didn't write about in the Doc such as how to make &lt;code&gt;.toml&lt;/code&gt; file, the syntax of &lt;code&gt;.toml&lt;/code&gt; file. And also, I didn't consider the users have different environment; some users use Linux, Some use Window, and Some use Mac. So I added instructions for different environments.&lt;/p&gt;




&lt;h4&gt;
  
  
  - Q6. How do users install and use your project now that it has been released? Provide links and some instructions.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/code-mage/" rel="noopener noreferrer"&gt;Code-Mage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the published version of my tool. User first needs to have Python 3.12 or later version installed on their machine.&lt;/p&gt;

&lt;p&gt;And then, users can downloade the tool using the following comands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;code-mage &lt;span class="c"&gt;# Window user&lt;/span&gt;
pip3 &lt;span class="nb"&gt;install &lt;/span&gt;code-mage &lt;span class="c"&gt;# Mac user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, they need to create their api_key at &lt;a href="https://openrouter.ai/docs/api-keys" rel="noopener noreferrer"&gt;openrouter&lt;/a&gt; Or &lt;a href="https://console.groq.com/keys" rel="noopener noreferrer"&gt;Groq&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They can set up their key with commands as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-api-key
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-api-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or they can create &lt;code&gt;.toml&lt;/code&gt; file in their home directory. They can set other options in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vi ~/.codemage-config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add the following environment settings in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# the double quotes for string values are necessary.&lt;/span&gt;

&lt;span class="py"&gt;model&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"groq"&lt;/span&gt; &lt;span class="c"&gt;# if you wish to use OPEN ROUTER you can just delete this line&lt;/span&gt;
&lt;span class="py"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;YOUR-GROQ-API-KEY&amp;gt;"&lt;/span&gt;
&lt;span class="py"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;YOUR-OPEN-ROUTER-API-KEY&amp;gt;"&lt;/span&gt;
&lt;span class="py"&gt;language&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"java"&lt;/span&gt; &lt;span class="c"&gt;# you can use any of the supported languages&lt;/span&gt;
&lt;span class="py"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# if you wish to get the output streamed, set it `true`&lt;/span&gt;
&lt;span class="py"&gt;token_usage&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# if you wish to get token_usage info, set it `true`&lt;/span&gt;
&lt;span class="py"&gt;output&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt; &lt;span class="c"&gt;# type any name for the output file without the extension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, they can use the tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codemage &lt;span class="nt"&gt;-v&lt;/span&gt;
codemage &lt;span class="nt"&gt;-h&lt;/span&gt;
codemage test.js &lt;span class="c"&gt;# assume there as test.js file in your current dir.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Project Chronicles - Release 0.3</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Sun, 17 Nov 2024 04:29:22 +0000</pubDate>
      <link>https://dev.to/jinger-ale/project-release-03-part-1-3f19</link>
      <guid>https://dev.to/jinger-ale/project-release-03-part-1-3f19</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://github.com/tarasglek/chatcraft.org" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; That I worked on
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Issues
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/issues/704" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/issues/704&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/issues/613" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/issues/613&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/issues/731" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/issues/731&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Pull Requests
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/pull/712" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/pull/712&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/pull/714" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/pull/714&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org/pull/732" rel="noopener noreferrer"&gt;https://github.com/tarasglek/chatcraft.org/pull/732&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Description
&lt;/h1&gt;

&lt;p&gt;This post is about a &lt;code&gt;Project-release 0.3&lt;/code&gt; for OSD600 course at Seneca College. For release 0.3, students were required to contribute to Open Source Project. This time, we were asked to contribute to a larger project, compared to what we worked on for Hacktoberfast, and make larger contributions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Progress
&lt;/h1&gt;

&lt;p&gt;For release 0.3, I decided to work on &lt;a href="https://github.com/tarasglek/chatcraft.org" rel="noopener noreferrer"&gt;the project&lt;/a&gt; that I worked on for my last commit during Hacktoberfast. Instead of finding a new repository, I wanted to work on a project that I already have some knowledge. I thought that this would be more helpful for understanding a larger Project and how larger projects are structured and what tech stacks they use and how they work. And more importantly, I really like &lt;a href="https://chatcraft.org" rel="noopener noreferrer"&gt;Chatcraft&lt;/a&gt;. I am very interested in &lt;code&gt;React&lt;/code&gt; and &lt;code&gt;Typescript&lt;/code&gt;, which are used in the project. So I continued working on this project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/704" rel="noopener noreferrer"&gt;Issue 1&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I looked at the issues on the repository and found &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/704" rel="noopener noreferrer"&gt;this issue&lt;/a&gt;. The issue was that for some of the llm models, it didn't provide proper icon.&lt;/p&gt;

&lt;h4&gt;
  
  
  How I fixed
&lt;/h4&gt;

&lt;p&gt;First, I had to figure out what the cause of this problem. My gut feeling told me that there must be some part where it handles the logic for which icon they should use. I started to find the part using &lt;code&gt;git grep&lt;/code&gt; by searching keywords such as &lt;code&gt;icon&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, and &lt;code&gt;avatar&lt;/code&gt;. Then, I found where this logic is implemented. The problem is that when it decides the icon, it checks the name of the model. However, some of the model names include uppercases, but the logic didn't check the uppercase, so I made it case-sensitive.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/613" rel="noopener noreferrer"&gt;Issue 2&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Since I worked on UI-related issues for the last couple contributions, I was getting more confedient with that, and I found another issue that's related to UI, which is about an unnecessary overflow in &lt;code&gt;PreferencesModal&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  How I fixed
&lt;/h4&gt;

&lt;p&gt;It was much quicker to find where the problem is occuring as I have already made two contributions. However, fixing the problem wasn't that easy. I knew that I needed to fix &lt;code&gt;css&lt;/code&gt; but didn't know how. The approach that I adopted was trial and error. I tried all the solutions that I could come up with. For example, I tried adding some padding, margin, height, or width, and changed some &lt;code&gt;css&lt;/code&gt; attributes such as &lt;code&gt;display&lt;/code&gt; or &lt;code&gt;overflow-x&lt;/code&gt;. Finally, I figured out one of the flex boxes need &lt;code&gt;weight&lt;/code&gt; specified so that it doesn't overflow its parent.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/731" rel="noopener noreferrer"&gt;Issue 3&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;While I was working on the previous issues. I found out that there were some bugs when I opened &lt;code&gt;PreferencesModal&lt;/code&gt;. For iPhone, when you touch &lt;code&gt;input&lt;/code&gt; element in &lt;code&gt;PrefeencesModal&lt;/code&gt;, it automatically zooms-in(Android phone doesn't automatically zoom-in). However, for some reason, you cannot zoom-out to normal size(zoom-in and zoom-out is prevented in any environment, whether it's mobile or ios or desktop). This was actually bothering me a lot while I was playing with &lt;code&gt;Chatcraft&lt;/code&gt; and when I was testing the app. Therefore, I opened an issue for this.&lt;/p&gt;

&lt;h4&gt;
  
  
  How I fixed
&lt;/h4&gt;

&lt;p&gt;Now it didn't take that long time to figure out where the code for this &lt;code&gt;UI element&lt;/code&gt; is located since I've been working on this project for two weeks. Although I knew which page is responsible for this, but I wasn't sure about which element I should fix. Nonetheless, I felt that it must be &lt;code&gt;Modal&lt;/code&gt; component, and I tried to look at it. However, I wasn't very confident with Chakra-UI, and some components of Chakra-UI looked deprecated. There was no offical docs for some components such as &lt;code&gt;Modal&lt;/code&gt;. Since there was no official docs and also ChatGPT didn't know well about Chakra-UI, I was frustrated a bit. Actually ChatGPT is so bad at Chakra-UI. I just started to follow the code and go deeper into the code. I did &lt;code&gt;ctrl + click&lt;/code&gt; on &lt;code&gt;Modal&lt;/code&gt; component in &lt;code&gt;VS Code&lt;/code&gt;, and it opened the library code for that. I did &lt;code&gt;ctrl + click&lt;/code&gt; on everywhere inside the library code, and finally found the prop interfaces that show what options you can send as a prop to the &lt;code&gt;Modal&lt;/code&gt; component. Some of them was about &lt;code&gt;scroll-block&lt;/code&gt; and &lt;code&gt;zoom&lt;/code&gt;. I tried those options, and it worked exactly the way I want. &lt;/p&gt;

&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;I am getting more confident with this project and more interested and fascinated by it. Now it takes less time to figure out problems and fixs it. I personally prefer to work on one project longer and deeper (vs. working on many different projects). I think there are pros and cons, but for now I think I need to stick to one project and go deeper so that I can get an understanding of a whole project.&lt;br&gt;
And also, I am overcoming the fear for a larger project. Chatcraft is not a huge project, but for me it is large enough, considering my programming skill level. I feel that I am growing and improving, which makes me really happy.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OSD600 - Lab08</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Thu, 14 Nov 2024 05:44:17 +0000</pubDate>
      <link>https://dev.to/jinger-ale/osd600-lab08-he6</link>
      <guid>https://dev.to/jinger-ale/osd600-lab08-he6</guid>
      <description>&lt;p&gt;Link to &lt;a href="https://github.com/gitdevjin/code-mage/actions/runs/11831363199" rel="noopener noreferrer"&gt;Action&lt;/a&gt;&lt;br&gt;
Link to &lt;a href="https://github.com/arilloid/addcom/pull/10" rel="noopener noreferrer"&gt;PR&lt;/a&gt; I opened for testing to my partner's repo&lt;/p&gt;
&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This post is about lab 08 for OSD600 course at Seneca College. This week, we learned CI(Continuous Integration). We integrated our testing into github workflow by setting them in &lt;code&gt;.yml&lt;/code&gt; file.&lt;/p&gt;


&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Q. How did you set up your GitHub Actions CI Workflow? What did the YAML for this workflow look like?
&lt;/h3&gt;

&lt;p&gt;This is my &lt;code&gt;.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;codemage - ci&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.12"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python ${{ matrix.python-version }}&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.python-version }}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Poetry&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;curl -sSL https://install.python-poetry.org | python3 -&lt;/span&gt;
        &lt;span class="s"&gt;export PATH="$HOME/.local/bin:$PATH"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;poetry install&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test with pytest&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;poetry run pytest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When writing a letter, it's always difficut to start the fisrt sentence. Your brain go blank like "how should I start?", but after that, it's not too hard. Likewise, when I start writing a setting file or setting up an app, the first set-up is always harder. However, github provides the &lt;a href="https://docs.github.com/en/actions/writing-workflows/using-workflow-templates" rel="noopener noreferrer"&gt;templates&lt;/a&gt; so I used them. With the template, it was not too hard.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yaml&lt;/code&gt; file looks to me like a json file without curly brakets and double-quotes. the foramt of &lt;code&gt;yaml&lt;/code&gt; is intuitive and easy to understand, but the github action commands(or options) are not familiar yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q.How did your partner's repo and testing setup differ from yours? What was it like writing tests for a project you didn't create?
&lt;/h3&gt;

&lt;p&gt;She and I both used &lt;code&gt;pytest&lt;/code&gt;; however, the testing code style was very different.&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Partner's Test code
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_generate_comments_no_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_parameters&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Test that the function raises an error if no API key is provided or found
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test_parameters&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API key must be provided&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;generate_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is her test code style&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# my test code.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestLoadConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;os.path.exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;toml.load&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_load_config_file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Simulate that the file exists
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="c1"&gt;# Simulate the contents of the file
&lt;/span&gt;        &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mock_openrouter_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Call load_config function
&lt;/span&gt;        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Assertions
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mock_openrouter_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;os.path.exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_load_config_file_not_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Simulate that the file does not exist
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="c1"&gt;# Call the function under test
&lt;/span&gt;        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Assertions
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some parts that have the same style, but some of them are very different although we use the same test framework. So I asked ChatGPT, and it says there are a few different styles to support flexibility for various test cases.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;function-based tests&lt;/li&gt;
&lt;li&gt;class-based tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I used class-based tests and she used function-based tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q. What do you think of CI now that you've set it up for yourself?
&lt;/h3&gt;

&lt;p&gt;My first impression is that it's so cool. Second, I think it's really good safety step. What often happens while working on a project is you fix one part and you are so happy and want to go to bed asap and have a good sleep, so you forget to test the code, and just push it to the repo. If you are working with others, this could be a disaster. And this CI prevents this mistake.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OSD600 - lab 07</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 08 Nov 2024 17:00:31 +0000</pubDate>
      <link>https://dev.to/jinger-ale/osd600-lab-07-4l1o</link>
      <guid>https://dev.to/jinger-ale/osd600-lab-07-4l1o</guid>
      <description>&lt;p&gt;Link to &lt;a href="https://github.com/gitdevjin/code-mage" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;br&gt;
Link to &lt;a href="https://github.com/gitdevjin/code-mage/commit/e71dcef555b8032d7204bd3fe159165d8a57fa8d" rel="noopener noreferrer"&gt;commit&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Description
&lt;/h1&gt;

&lt;p&gt;This post is about lab 07 for OSD600 course at Seneca College. This week we learned how to test our project. We learned about unit test, e2e(end to end), and integration test. &lt;/p&gt;
&lt;h1&gt;
  
  
  Progress
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, I needed to decide which test framewokr I am going to use. I asked chatGPT which one is most popular and also googled it and read some people's opinion. Then, I decided to use &lt;code&gt;pytest&lt;/code&gt; framework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, I started writing test code with each class that is called on top of the function call stacks. I chose the easist one, which is &lt;code&gt;load_config.py&lt;/code&gt;. It only contained one function.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;toml&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_config&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Load config file from the project's root directory
&lt;/span&gt;    &lt;span class="n"&gt;config_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Adjust path to project root
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function opens &lt;code&gt;.toml&lt;/code&gt; file, and read key-value pairs. I had to mock the config file and its content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestLoadConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;os.path.exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;toml.load&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_load_config_file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Simulate that the file exists
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="c1"&gt;# Simulate the contents of the file
&lt;/span&gt;        &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mock_openrouter_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Call load_config function
&lt;/span&gt;        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Assertions
&lt;/span&gt;        &lt;span class="n"&gt;mock_os_exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;mock_toml_load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codemage-config.toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mock_openrouter_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;code&gt;@patch&lt;/code&gt; to mock the file, file status(exists or not), and the content. Then I checked if the file is called with the path and if file content is correct.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Third, I tested &lt;code&gt;Api&lt;/code&gt; class. Since this is also independent and called on the top of the function stack.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;supported_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openrouter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openrouter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;supported_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is not suppored. Model Supported: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;supported_model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# default api_url and api_model
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://openrouter.ai/api/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sao10k/l3-euryale-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# api_url and api_model when the provider is groq
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.groq.com/openai/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3-8b-8192&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream_flag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;completion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;extra_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;only display the code without any explanation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translate this to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_lang&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; language: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stream_flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;completion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tested the constructor first and then I tested the method &lt;code&gt;call_api&lt;/code&gt;. Testing constructor was not difficult. I just needed to make a &lt;code&gt;mock_config&lt;/code&gt;, and &lt;code&gt;mock_args&lt;/code&gt;. Testing the method was pretty tough. I had to mock the response object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestApiWithEnv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_openrouter_api_key_from_toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_groq_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Mock OpenAI response
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Return a mock response object with a `choices` attribute
&lt;/span&gt;        &lt;span class="n"&gt;mock_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mock_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_response&lt;/span&gt;

    &lt;span class="c1"&gt;# Test when model is supported
&lt;/span&gt;    &lt;span class="nd"&gt;@patch.dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_api_key_from_env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_groq_api_key_from_env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.api.OpenAI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_api_with_openrouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_openai_class&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Mock the OpenAI client and its methods
&lt;/span&gt;        &lt;span class="n"&gt;mock_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# When the code create OpenAI class inside call_api(), it's replaced by mock_openai_class
&lt;/span&gt;        &lt;span class="n"&gt;mock_openai_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock_client&lt;/span&gt;
        &lt;span class="n"&gt;mock_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="c1"&gt;# Create an instance of the Api with a supported model
&lt;/span&gt;        &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openrouter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;

        &lt;span class="c1"&gt;# Simulate an API call
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;some_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Check if the API call was made with the expected arguments
&lt;/span&gt;        &lt;span class="n"&gt;mock_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;extra_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sao10k/l3-euryale-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;only display the code without any explanation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translate this to python language: some_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Assert the response content
&lt;/span&gt;        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, there is a way to mock api call provided. I used&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.api.OpenAI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of my Test codes for &lt;code&gt;Api&lt;/code&gt; Class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestApiWithEnv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_openrouter_api_key_from_toml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_groq_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Mock OpenAI response
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Return a mock response object with a `choices` attribute
&lt;/span&gt;        &lt;span class="n"&gt;mock_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mock_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_response&lt;/span&gt;

    &lt;span class="c1"&gt;# Test when model is supported
&lt;/span&gt;    &lt;span class="nd"&gt;@patch.dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_api_key_from_env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_groq_api_key_from_env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.api.OpenAI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_api_with_openrouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_openai_class&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Mock the OpenAI client and its methods
&lt;/span&gt;        &lt;span class="n"&gt;mock_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# When the code create OpenAI class inside call_api(), it's replaced by mock_openai_class
&lt;/span&gt;        &lt;span class="n"&gt;mock_openai_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock_client&lt;/span&gt;
        &lt;span class="n"&gt;mock_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="c1"&gt;# Create an instance of the Api with a supported model
&lt;/span&gt;        &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openrouter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;

        &lt;span class="c1"&gt;# Simulate an API call
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;some_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Check if the API call was made with the expected arguments
&lt;/span&gt;        &lt;span class="n"&gt;mock_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_called_once_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;extra_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sao10k/l3-euryale-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;only display the code without any explanation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translate this to python language: some_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Assert the response content
&lt;/span&gt;        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used ChatGPT; it gave me good hints, but didn't work well, I had to make some changes and it worked. If I am being honest, I am still confused how it works, but it looks like it tests the code as it should. I think I need to study more to fully understand and write test code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fourth, the most difficult part was testing &lt;code&gt;Translator&lt;/code&gt; class. It calls other functions that requires mock environments such as openeing a file from file system and calling api.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my test code for &lt;code&gt;translate()&lt;/code&gt; function in &lt;code&gt;Translator&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestTranslator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fixture for simulating command-line arguments.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_usage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;mock_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mock_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_response&lt;/span&gt;

    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;builtins.open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_callable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Mock open
&lt;/span&gt;    &lt;span class="nd"&gt;@patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.translator.Api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Mock Api class
&lt;/span&gt;    &lt;span class="nd"&gt;@patch.object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Translator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_Translator__get_output_filename&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translated_test.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_get_output_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;mock_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fake_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Initialize Translator instance
&lt;/span&gt;        &lt;span class="n"&gt;translator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Translator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;mock_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mock_open&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock_file&lt;/span&gt;

        &lt;span class="c1"&gt;# Mock the Api's call_api method
&lt;/span&gt;        &lt;span class="n"&gt;mock_api_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mock_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock_api_instance&lt;/span&gt;
        &lt;span class="n"&gt;mock_api_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock_api_call&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="n"&gt;translator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./example/test.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;mock_api_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Translated code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;mock_open&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_any_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./example/test.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;mock_open&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert_any_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translated_test.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What was challenging was that I didn't understand how it knows which mock is for &lt;code&gt;api_call()&lt;/code&gt; and which mock is for &lt;code&gt;open()&lt;/code&gt; when I made two &lt;code&gt;Mock&lt;/code&gt; objects. I tested it by changing the order of arguments, and the name of arguments. I think it maps &lt;code&gt;@patch&lt;/code&gt; result to the arguments by order and name. I don't understand how exactly it works, but I learned that the order and name matters and I should make sure that they followes the order in which &lt;code&gt;@patch&lt;/code&gt; is called and the name.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lastly, I couldn't test &lt;code&gt;main&lt;/code&gt; function as it calls many other functions which require &lt;code&gt;mock&lt;/code&gt; enviornment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Testing the whole &lt;code&gt;main&lt;/code&gt; function would make test too complicated. However, I've already tested all the other functions except for arguments parser. Therefore, I refactored the argument-parsing logic. I made a new function for parsing arguements and imported it in the &lt;code&gt;main&lt;/code&gt; function. I believe this can to some degree ensure that all the logics of the tool covered, although testing for everything together from start to end is not covered.&lt;/p&gt;

&lt;p&gt;This is a part of my testing code for argument parser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# A mock configuration that mimics the structure of the actual config dictionary.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_usage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;# Test with no arguments
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_arg_parser_no_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys.argv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arg_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_files&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# default from mock_config
&lt;/span&gt;        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# default from mock_config
&lt;/span&gt;        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_usage&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


&lt;span class="c1"&gt;# Test with source file
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_arg_parser_with_source_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys.argv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arg_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_files&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Reflection
&lt;/h1&gt;

&lt;p&gt;At first, I thought that it is going to be easy. However, it was really tough, especially for mocking &lt;code&gt;object&lt;/code&gt;, &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;file open()&lt;/code&gt;, &lt;code&gt;http request&lt;/code&gt;, and &lt;code&gt;http response&lt;/code&gt;. It also was kind of fun. From this lab, I learned how to test code thoroughly and how important it is to modulize the code so that I can test the code in a isolated environment. It's not perfect but at least it guarantees a certain level of robustness. &lt;/p&gt;

&lt;h3&gt;
  
  
  Q1. Which testing framework/tools did you choose? Why did you choose them? Provide links to each tool and briefly introduce them.
&lt;/h3&gt;

&lt;p&gt;I chose &lt;a href="https://docs.pytest.org/en/stable/#" rel="noopener noreferrer"&gt;&lt;code&gt;pytest&lt;/code&gt;&lt;/a&gt;; but I also used some of the methods provided by &lt;code&gt;unittest&lt;/code&gt;, which is provided by python as a default.&lt;/p&gt;

&lt;h3&gt;
  
  
  How did you set them up in your project? Be detailed so that other developers could read your blog and get some idea how to do the same.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  install &lt;code&gt;pytest&lt;/code&gt; if not installed yet.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add &lt;span class="nt"&gt;--dev&lt;/span&gt; pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running &lt;code&gt;pytest&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This command will run files named &lt;code&gt;test_*.py&lt;/code&gt; or &lt;code&gt;*_test.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more detailed test result, you can use &lt;code&gt;-v&lt;/code&gt; option&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run pytest &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for more detailed test information&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run pytest &lt;span class="nt"&gt;-vv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Writing TestCode
&lt;/h4&gt;

&lt;p&gt;You should name your test class and method as follows:&lt;/p&gt;

&lt;h4&gt;
  
  
  Class name starts with &lt;code&gt;Test&lt;/code&gt;
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Method name starts with &lt;code&gt;test_&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestMyFeature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# class name
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_feature_functionality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# method name
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Q3. How did you handle LLM response mocking?
&lt;/h3&gt;

&lt;p&gt;In the progress section, I explained about this, so I will skip here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q4. What did you learn while writing your test cases? Did you have any "aha!" moments or get stuck?
&lt;/h3&gt;

&lt;p&gt;What I learned is how important it is to design the code strutures. I learend that good design pattern is not just for making code look better and reusability but also for testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q5. Did your tests uncover any interesting bugs or edge cases?
&lt;/h3&gt;

&lt;p&gt;My test doesn't cover some parts such as streaming out response object and testing from start to zero like total integration test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q6. What did you learn from this process? Had you ever done testing before? Do you think you'll do testing on projects in the future?
&lt;/h3&gt;

&lt;p&gt;My first experience with testing was in my second semester. I took the software testing course that was newly introduced. I was the first student in seneca who took the course. At first, I really didn't like it. I thought that it was a waste of time. test code was 4~5 times larger and took 4~5 times more than writing the logic of the program. It was grinding. However, now I kind of like it. When I see the green colored results &lt;code&gt;pass&lt;/code&gt;, I feel really good. Making mock environment is still hard and somewhat stressful, but thinking about edge cases is actually really fun. It is kind of similar to Probability and Statistics in Math like thinking about all the possible cases and cover it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OSD600 - lab06</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 01 Nov 2024 04:31:44 +0000</pubDate>
      <link>https://dev.to/jinger-ale/osd600-lab06-39p8</link>
      <guid>https://dev.to/jinger-ale/osd600-lab06-39p8</guid>
      <description>&lt;p&gt;Link to &lt;a href="https://github.com/gitdevjin/code-mage" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&lt;br&gt;
Link to &lt;a href="https://github.com/gitdevjin/code-mage/commit/f755199ccbedd687f8e46977d1f3dc8c016e0f8d" rel="noopener noreferrer"&gt;commit&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Description
&lt;/h1&gt;

&lt;p&gt;This post is about lab 06 for OSD600 course at Seneca College. This week we learned Static Analysis Tooling such as Formatter(prettier, Ruff) and Linter(Black, Ruff, ESLint). Using those tools, we made our code more consistent regardless of where it is written or who writes it. And also, we practiced &lt;code&gt;git commands&lt;/code&gt; such as &lt;code&gt;git merge&lt;/code&gt; and &lt;code&gt;git rebase&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Tasks
&lt;/h1&gt;
&lt;h1&gt;
  
  
  Q1. Which tools did you choose? Why did you choose them? Provide links to each tool and briefly introduce them.
&lt;/h1&gt;

&lt;p&gt;I use &lt;a href="https://docs.astral.sh/ruff/formatter/" rel="noopener noreferrer"&gt;Ruff&lt;/a&gt; for both formatter and linter. When I was reading the instruction for this lab, I found that Ruff can be used for both formatter and linter. I thought that I would be more conveninent and efficient to use one tool for the people who would work on this project as well as for myself. Ruff is orginally maded for formatter, but then its features expanded to Linter. The upside to this tool is that it's really faster and also compatable with other linters such as &lt;a href="https://pypi.org/project/black/" rel="noopener noreferrer"&gt;Black&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Q2. How did you set them up in your project? Be detailed so that other developers could read your blog and get some idea how to do the same.
&lt;/h1&gt;

&lt;p&gt;I've created my own organized notes on GitHub to document what I've learned, as the content is quite extensive. I will also share the &lt;a href="https://github.com/gitdevjin/bits-of-knowledge/blob/main/python/tools.md" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Install Ruff
&lt;/h1&gt;

&lt;p&gt;Include the following codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pyproject.toml file&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;poetry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;ruff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.7.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Ruff Formatter
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Formatter Configuration
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;pyproject.toml&lt;/code&gt; file, configure the Ruff formatter as the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ruff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;exclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nv"&gt;"tests/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Ignore&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt;
    &lt;span class="nv"&gt;"docs/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Ignore&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt;
    &lt;span class="nv"&gt;"*.pyc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Ignore&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;compiled&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;
    &lt;span class="nv"&gt;"migrations/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Ignore&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt;
    &lt;span class="nv"&gt;"example/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"__pycache__/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"*.env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"**/*.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ruff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"double"&lt;/span&gt;
&lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"tab"&lt;/span&gt;
&lt;span class="n"&gt;docstring&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;docstring&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docstring-code-format = true&lt;/code&gt; : This will format code that starts with &amp;gt;&amp;gt;&amp;gt; inside &lt;code&gt;""" ... """&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For example, If &lt;code&gt;docstring-code-format = true&lt;/code&gt; option is applied to the following code,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Calculate the square of a number.

    Example:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Outputs 25
&lt;/span&gt;        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;long_calculation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;long_calculation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Outputs 1300
&lt;/span&gt;    &lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will become formatted as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Calculate the square of a number.

    Example:
&lt;/span&gt;&lt;span class="gp"&gt;        &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Outputs 25
&lt;/span&gt;        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;long_calculation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;     &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;calculate_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;long_calculation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Outputs 1300
&lt;/span&gt;    &lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docstring code can be executed. Refer to &lt;a href="https://docs.python.org/3/library/doctest.html" rel="noopener noreferrer"&gt;doctest Docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the &lt;code&gt;Ruff formatter&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run ruff format &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Ruff Linter
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Linter Configuration
&lt;/h2&gt;

&lt;p&gt;Since I am using ruff formatter together, I only need a bit more configuration settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ruff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"E4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"E7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"E9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"F"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"F841"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  I asekd ChatGPT what those are for.
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;E4&lt;/code&gt;: This code typically corresponds to various syntax errors or issues related to the structure of your code. It may include checks for problems such as unclosed parentheses, braces, or other syntax-related issues.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;E7&lt;/code&gt;: This code is generally related to type errors or issues involving type annotations. It may indicate that there are inconsistencies or issues with type hints in your code, which can lead to confusion or runtime errors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;E9&lt;/code&gt;: This error code often relates to import errors or issues with the organization of your import statements. It can flag problems such as unused imports or circular imports that can complicate module loading.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;F&lt;/code&gt;: This category usually encompasses formatting issues. It can include a variety of stylistic checks, such as line length, whitespace usage, and general adherence to PEP 8 (the Python style guide).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;F841&lt;/code&gt;: This code specifically checks for assigned variables that are never used.&lt;/p&gt;

&lt;h3&gt;
  
  
  We could also do:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ruff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;per&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ignores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;"__init__.py"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"E402"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;"**/{tests,docs,tools}/*"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"E402"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  I asked ChatGPT what those configurations are for:
&lt;/h3&gt;

&lt;p&gt;ChatGPT =&amp;gt; The &lt;code&gt;E402&lt;/code&gt; error, which means "module level import not at top of file," occurs when import statements are not placed at the top of a Python file. According to PEP 8, the Python style guide, all imports should be at the top of the file, right after any module comments and docstrings but before any other code.&lt;/p&gt;

&lt;p&gt;Here are common scenarios where E402 might happen:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Conditional Imports:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;  &lt;span class="c1"&gt;# E402 error: Import is not at the top level of the file
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Delayed Imports for Performance Reasons:
&lt;/h3&gt;

&lt;p&gt;Sometimes, you might place an import further down in the file to avoid unnecessary imports until they are actually needed, such as in a function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;  &lt;span class="c1"&gt;# E402 error: Import is inside a function
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In those scenarios, you can use the configuration for the files that need to ingore the rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to skip linting some pieces of code in a file
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Ignore Specific Lines
&lt;/h3&gt;

&lt;p&gt;You can add an &lt;code&gt;# noqa&lt;/code&gt; comment at the end of a line to ignore linting on that specific line. To ignore specific rules, specify the rule codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;groq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# noqa: F632
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, Ruff will ignore the &lt;code&gt;F632&lt;/code&gt; warning on that line.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ignore a Block of Code
&lt;/h3&gt;

&lt;p&gt;To ignore a block of code, wrap the code with &lt;code&gt;# noqa: BEGIN&lt;/code&gt; and &lt;code&gt;# noqa: END&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# noqa: BEGIN
# This code block will be ignored by the linter
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;  &lt;span class="c1"&gt;# Normally flagged as E402
# noqa: END
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Ignore Rules for the Whole File
&lt;/h3&gt;

&lt;p&gt;To ignore specific rules for the entire file, add a comment at the top of the file listing the rule codes to ignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ruff: noqa: E402, F632
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is useful if the whole file has patterns that would otherwise be flagged by Ruff, such as non-top-level imports or value comparisons using is&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the &lt;code&gt;Ruff Linter&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run ruff check &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Q3. What did the tools find in your code? Did you have to fix a lot of issues?
&lt;/h1&gt;

&lt;p&gt;Python is already a bit strict when it comes to its formatting such as indentation or line changes, formatter didn't do a lot; only in the main function it changed quite a bit. However, Linter actually caught some syntax errors that I missed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Formatter in &lt;code&gt;codeMage.py&lt;/code&gt; file
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr1xjom5gfu8c8zt7b7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr1xjom5gfu8c8zt7b7y.png" alt="Image description" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  After Formatter
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukn50rynqpwk0x9eskbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukn50rynqpwk0x9eskbp.png" alt="Image description" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Linter found
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52iw4dun4b3z9csdya1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52iw4dun4b3z9csdya1k.png" alt="Image description" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Q4.How did you get the tools to run from the command line?
&lt;/h1&gt;

&lt;p&gt;I think I answered this question above, and since the post is getting too long, I will not make an redunant writing. Sometimes when the post is too long, &lt;code&gt;Dev.to&lt;/code&gt; seems to get some bugs. Some part of the content disappears.&lt;/p&gt;

&lt;h1&gt;
  
  
  Q5. How did you integrate the tools with your editor/IDE?
&lt;/h1&gt;

&lt;p&gt;These are the steps that I followed. I contained them in &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; in my project&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Python Extension for VS Code (if not already installed):
&lt;/h3&gt;

&lt;p&gt;The Python extension for VS Code is needed to enable Python-specific features, such as linting and formatting integration. Open VS Code, go to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X on macOS),search for "Python" by Microsoft and install it if you haven’t already.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ruff VS Code Extension:
&lt;/h3&gt;

&lt;p&gt;Install the Ruff extension in VS Code to enable real-time linting and formatting.&lt;br&gt;
In the Extensions view, search for "Ruff," and install the extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manually Running Ruff Formatter and Linter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Run the &lt;code&gt;Ruff formatter&lt;/code&gt; with the following command in the root directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run ruff format &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the &lt;code&gt;Ruff Linter&lt;/code&gt; with the following command in the root directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run ruff check &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Q6. What did you learn from the process?
&lt;/h1&gt;

&lt;p&gt;When I looked around gitHub and saw all these files, I didn't like them. It's because I didn't know them and I didn't need the necessity. As I learned it now and know how to use it, I love them. It's really useful and helpful. Especially when you are working with Dynamically Typed Language, it is so helpful. I think I will use these tools every time I start a new project, from now on. It's so cool&lt;/p&gt;

</description>
      <category>osd600</category>
    </item>
    <item>
      <title>Hacktoberfest - Week 5</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Tue, 29 Oct 2024 22:43:09 +0000</pubDate>
      <link>https://dev.to/jinger-ale/hacktoberfest-week-5-4cfo</link>
      <guid>https://dev.to/jinger-ale/hacktoberfest-week-5-4cfo</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tarasglek/chatcraft.org" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; that I worked on.&lt;br&gt;
&lt;a href="https://github.com/tarasglek/chatcraft.org/issues/655" rel="noopener noreferrer"&gt;Issue&lt;/a&gt; I fixed.&lt;br&gt;
&lt;a href="https://github.com/tarasglek/chatcraft.org/pull/705" rel="noopener noreferrer"&gt;PR&lt;/a&gt; I opened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;For this last PR, I really wanted to contribute to a larger project. I started to read other classmates' blogs, the issues they worked on, and their contributions. I found out that some of the classmates made a PR to &lt;a href="https://github.com/tarasglek/chatcraft.org" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;, and also during the classes, Professor introduced this project; so I was interested in this. I started to look around the issues in this repo, and I found &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/655" rel="noopener noreferrer"&gt;this issue&lt;/a&gt;. I thought that I could fix this issue. Then, I started to read the code. It was very complicated to me. I only had little knowledge about react and typescript. And the structure is very well organized in a object-oriented programming way. However, sometimes I feel like when codes are too well organized, it feels a little bit like a maze. It took me many hours to understand where I should look into in order to fix the problem. Finally, I found the code that I need to change. I made changes and did some experiments and fixed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whenever I read code of a large project, it takes me a very long time to get just a little understanding. Therefore, it was not easy to get started.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;I wasn't familiar with the technologies used in the project. I wasn't familiar with &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;Typescript&lt;/code&gt;, &lt;code&gt;Chakra UI&lt;/code&gt;, and &lt;code&gt;Dexie&lt;/code&gt;; so I had to study or search whenever I encounter a piece of code that I don't understand at all. Especially for Chakra UI, I wanted to add &lt;code&gt;padding-bottom&lt;/code&gt; but the syntax was very different, I went to the offical Docs page and spent quite a bit of time, for Chakra UI, ChatGPT wasn't helpful at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I gained from this experience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First, I love this project, The code is really clean, and well organized. And it uses the tech stacks that I want to learn. and the UI is really neat and modern&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;Second, just reading the code many hours (not because I intended, but because I had to find where I should fix it), I learned a lot about React. It was amazing that I just read the code and learned a lot. It was much more effective than watching React lecture on Youtube. Of course it's because I already had a bit of knowledge of React. Nonetheless, I didn't expect that I would learn a lot by just reading code. When I have more time, I am going to read the code of this Chatcraft repo, and I will try to make something similar to this. It's beautiful app&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;Third, I overcame the fear of working on a large project. I wouldn't say that I've completely overcome the fear; however, at least I tried it, and made some PRs. It's still really daunting to read and work on large project, but I think I learned that they are not invincible monster. They are mortal(just metaphor; I mean, touchable or fixable)&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Hacktoberfest Recap
&lt;/h2&gt;

&lt;p&gt;I think I didn't make any PR that can be counted on Hacktoberfest, but I don't care much. I learned a lot from this experience, and that's all I wanted and needed. Even if I get lower marks due to uncounted PRs, I am okay(unless I fail this course; as I could have Visa problem). I am glad that I was forced to step out of my comfort zone. If the Professor is reading this post, I want to thank you. I sincerely appreciate for pushing me out of my comfort zone, it was tough and I was stressed out but I learned a lot. Now I know how to participate in Open Source Project, I will keep looking around Open Source Projects and read them and work on them.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest - Week 4</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 25 Oct 2024 16:26:33 +0000</pubDate>
      <link>https://dev.to/jinger-ale/hacktoberfest-week-4-478f</link>
      <guid>https://dev.to/jinger-ale/hacktoberfest-week-4-478f</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/devlup-labs/dev-playground" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; that I worked on&lt;br&gt;
&lt;a href="https://github.com/devlup-labs/dev-playground/issues/14" rel="noopener noreferrer"&gt;Issue&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/devlup-labs/dev-playground/pull/22" rel="noopener noreferrer"&gt;Pull&lt;/a&gt; Request that I opened&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;I have worked on a huge repo(ladybird) and miserably failed on fixing it. I was deeply frustrated, my neck, back, eyes sored from long sitting and watching screen, and the due date was comming. I really wanted to make a PR to a huge repo, but I failed. As a result, I started looking for a smaller and easier repo that I can fix. I found one issue that I think I can easily fix. It was just fixing the password checker function. Previously, it couldn't properly detect the numbers in password; it could only check the number in the first character(e.g. "1abcdefg" or "2345abcd"). For example, if the password is "abc5defg" then it didn't recognize the number and will generate an error "the password should contain at least one digit". Now, it can check the numbers in any position.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;This issue was too simple and too easy for my third PR. I feel bad. I really feel bad. I really want to contribute to a larger repo. However, I think my ability is just this much. However; for the last PR for release 0.2, I will try my best to make a PR to bigger repo whether I fail or lose marks for not finishing fourth PR. My pride doesn't allow me to be satisfied with having those simple issues solved.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest - Week 3(failed)</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Fri, 25 Oct 2024 16:04:02 +0000</pubDate>
      <link>https://dev.to/jinger-ale/hactoberfest-week3-2ckl</link>
      <guid>https://dev.to/jinger-ale/hactoberfest-week3-2ckl</guid>
      <description>&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/LadybirdBrowser/ladybird" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; that I worked on&lt;br&gt;
&lt;a href="https://github.com/LadybirdBrowser/ladybird/issues/1617" rel="noopener noreferrer"&gt;Issue 1&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/LadybirdBrowser/ladybird/issues/1833" rel="noopener noreferrer"&gt;Issue 2&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;I was working on Ladybird for a long long time. The issue at first looked easy to fix. It was to fix a bug that &lt;code&gt;legend&lt;/code&gt; element is not displayed on the top left corner of the top border line of &lt;code&gt;fieldset&lt;/code&gt;  element. I found the code that handles the css of &lt;code&gt;legend&lt;/code&gt; and &lt;code&gt;fieldset&lt;/code&gt; element. I could make it look similar to the proper &lt;code&gt;legend&lt;/code&gt; element on chrome or other browers. However, I felt like this is the right way to fix and the problem comes frome somewhere else. In addtion, it didn't work exactly the way it should. Therefore, I didn't make a PR for this.&lt;/p&gt;

&lt;p&gt;Secondly, I worked on a similar issue on this repo. It was that when an element has &lt;code&gt;display: flex&lt;/code&gt; attribute applied to it, &lt;code&gt;a:hover&lt;/code&gt; attribute doesn't work. However, with &lt;code&gt;display: block&lt;/code&gt; or without &lt;code&gt;display&lt;/code&gt; attribute, it works fine. For this issue, I couldn't even find the place where the code for this issue exists. I feel like those two issues have similar casues, but I couldn't figure out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest - Week 2</title>
      <dc:creator>Hyunjin Shin (Jin)</dc:creator>
      <pubDate>Sat, 12 Oct 2024 01:21:34 +0000</pubDate>
      <link>https://dev.to/jinger-ale/hacktoberfest-week-2-31lk</link>
      <guid>https://dev.to/jinger-ale/hacktoberfest-week-2-31lk</guid>
      <description>&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ozkary/UISpark" rel="noopener noreferrer"&gt;Repo&lt;/a&gt; that I worked on&lt;br&gt;
&lt;a href="https://github.com/ozkary/UISpark/issues/1" rel="noopener noreferrer"&gt;Issue&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/ozkary/UISpark/pull/2" rel="noopener noreferrer"&gt;Pull Request&lt;/a&gt; that I opened&lt;/p&gt;

&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I was searching for issues with keyward good first issue. And I found this Repo. It was a project that provides useful tools for web development. I think the project has started very recently, so it only had one module of formatting phone numbers. I thought that this project is really interesting, and it will be very useful. And there was one issue in this project. The issue was to make the tool support international phone numbers; currently it only supported one type of format. I left a comment asking if I can work on the issue, and then started working on it. The project used jQuery, which I had no experience of at all. Therefore, I had to study jQuery first. I studied jQuery only as much as I need to understand the project. After that, I thought about the logic of how to convert different types of international phone numbers. The problem was, I wasn't sure about the use cases. For example, "Do users provide what country the phone number is for?" or "Should the program figure it out by the entered country code?" I wrote the code with the assumpution that the user select country-code with dropdown box, since this is the most common use case as far as I experienced. I started writing codes, but the logic was really difficult. I had to use regex, and also the maintainer wanted it format the phone number as users type them. I searched docs for regex and used AI for some hints. Finally, I could make it work. Currently the tool now supports number for US, UK, FR, KR. However, following the same logic, they can easily add supports for more international phone numbers. There was a test code, so I also needed to write a test code for my changes. It used chai and jsdom dependencies for testing, so I also had to study about them a bit. Foutunately, I finished writing my code and test code, and the test successfully passed. Then, I opened pull request. I mentioned that I wrote the code assuming that the user select the country-code for their phone number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection
&lt;/h3&gt;

&lt;p&gt;I was glad that I contributed to a project. However, today I had a OSD600 course in the morning. And other students talked about what repo they worked on and what issues they handled. They worked on a huge project that looks very difficult, and they got their PRs accepted and merged. That gave me imposter syndrom. I was quite depressed by how bad and unimpressive my PR and contributions are. However, at the same time, that was really motivating. I thought that I should also try to contribute to a huge project. And there was a guy Peter. He introduced his unsuccessful attempt to contribute to VSCode. Although he didn't succeed, he tried it. I thought that it was very brave and cool. That was really encouraging and impressive. For the next PRs, I will try to contribute to a huge project, whether I fail or not. I think even though I fail, it will be a great experience and I will learn a lot from the failure.&lt;/p&gt;

</description>
      <category>osd600</category>
    </item>
  </channel>
</rss>
