Berat Bozkurt

Merhaba, Ben Berat Bozkurt 🤙🏼

Frontend developer olarak çalışıyorum

Fotoğraf çekmeyi, seyehat etmeyi seviyorum. Ayrıca yararlı bulduğum içerikleri twitter'da, açık kaynak projelerimi github'ta, çektiğim fotoğrafları ise unsplash üzerinden paylaşıyorum. Ayrıca bu blog da ise deneyimlerimden teknik yazılarımdan ve hayatımdaki gelişmelerden bahsediyorum.

# Son Yazılar

React Uygulamasına Test Yazalım

Yazılım08 Nisan 2023 7 dk okuma

Uzun zamandır beklenen bir yazı dizisiydi. Aslında ben de test üzerine kendimi geliştirmek için ufakta olsa birkaç bir şey yapmak istiyordum. Bu yazı da anlatacağım için benim için bir bahane olmuş oldu. Ee bildiğiniz gibi eğer öğrenmek istediğin bir şey varsa onu birisine anlatmak gerek. Gerek ki daha iyi öğrenesin... O yüzden karşınızdayım :)

Yazıya başlamadan önce hemen backlink geçeyim. Serinin 1. yazısını okumayanlara buraya alalım. React Uygulamasına Test Yazalım #1

Test nedir, unit test nedir, integration test nedir gibi kısımlara giriş yapmadan direk konunun içine gireceğiz. Daha akılda kalıcı olması için bir proje geliştirdim ve bunu github üzerinden herkese açık bir şekilde paylaştım. Hem bu şekilde sizler de projeyi inceleyebilir ve test konusunu en azından bir noktaya kadar anlayabilirsiniz.

Projeyi İnceleyelim

Aslında projeyi basit tutmaya çalıştım. Bu şekilde odaklanmamız gereken konuya daha iyi bir biçimde kafa yorabiliriz. Proje, basit bir misafir defter uygulaması. Tamamen localde çalışan, api bağlantısı olmayan, birkaç component'ten oluşan bir proje. Projenin canlı halini Guestbook adresinden inceleyebilirsiniz.

Github üzerinden kaynak kodlarına ulaşmak isterseniz de github.com/berat/guestbook adresinden ulaşabilirsiniz. Ayrıca projeyi geliştirirken ekran kaydı alıp youtube üzerinden paylaştım.

Unit Testlerle Başlayalım

Aslında tam olarak hangi durumları keşfetebilirim pek bilemedim. Ama aklıma gelenler sırasıyla şunlar;

  • Component render oluyor mu?
  • Disable/enable durumları doğru bir şekilde çalışıyor mu?
  • Input value'ları doğru bir şekilde çalışıyor mu?
  • Buton tıklamaları sonra olan adımlar doğru bir şekilde gerçekleşiyor mu?

gibi sorulara cevap almaya çalıştım. Tabii yazdığım test yine basit kalıyor. Bunun daha ilerisi redux bağlantısı ve api bağlantısı olan bir uygulamada mock datalar ile test yazmak ve store değişikliğini test etmek olacaktır. Ama tabii bunlar ileri konular. Şimdilik bunlar işimizi görecektir.

Yorumun yazılacağı form component

import { memo, useEffect, useState } from 'react';

const INITIAL_STATE = {
  name: '',
  comment: ''
};

const Form = ({ setComments }) => {
  const [values, setValues] = useState(INITIAL_STATE);
  const [buttonDisabled, setButtonDisabled] = useState(true);

  const handleChange = event => {
    const { name, value } = event.target;
    setValues({ ...values, [name]: value });
  };

  useEffect(() => {
    const getValues = Object.values(values);

    const isEmpty = getValues.some(item => item === '');

    if (isEmpty) setButtonDisabled(true);
    else setButtonDisabled(false);
  }, [values]);

  const onSubmit = () => {
    setComments(prev => [
      ...prev,
      {
        id: Math.floor(Math.random() * 999999),
        name: values.name,
        comment: values.comment
      }
    ]);
    // reset values
    setValues(INITIAL_STATE);
  };

  return (
    <div id="form">
      <input
        type="text"
        placeholder="Adınız"
        name="name"
        value={values.name}
        onChange={handleChange}
      />
      <textarea
        rows={2}
        placeholder="Mesajınız"
        name="comment"
        value={values.comment}
        onChange={handleChange}
      ></textarea>
      <button onClick={onSubmit} disabled={buttonDisabled}>
        Gönder
      </button>
    </div>
  );
};

export default memo(Form);

Burada bir input bir textarea bir de button olan basit bir component. Bu componentin çalışması için de gerekli olan bazı fonksiyonlar var. Bunları özetlemek gerekirse şöyle;

  • handleChange fonksiyonu input ve textarea'ların value'larını state'e kaydetmek için kullanılıyor.
  • useEffect hook'u ise input ve textarea'ların boş olup olmadığını kontrol ediyor. Boş ise buton disable oluyor.
  • onSubmit fonksiyonu ise butona tıklandığında çalışıyor. Burada da setComments fonksiyonu ile state'e yeni bir yorum ekleniyor. Ayrıca input ve textarea'ların value'ları sıfırlanıyor.

Yorumun yazılacağı form component testi

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Form from './Form';

describe('should render', () => {
  test('input', () => {
    render(<Form />);

    const input = screen.getByPlaceholderText('Adınız');

    expect(input).toBeInTheDocument();
  });
  test('textarea', () => {
    render(<Form />);

    const textarea = screen.getByPlaceholderText('Mesajınız');

    expect(textarea).toBeInTheDocument();
  });
  test('button', () => {
    render(<Form />);

    const button = screen.getByRole('button');

    expect(button).toBeInTheDocument();
  });
});

test('case button dissable props', () => {
  render(<Form />);

  // get elements
  const input = screen.getByPlaceholderText('Adınız');
  const textarea = screen.getByPlaceholderText('Mesajınız');
  const button = screen.getByRole('button');

  expect(button).toBeDisabled();

  userEvent.type(input, 'test');
  userEvent.type(textarea, 'test');

  expect(button).not.toBeDisabled();
});

Test caselerin açıklamalarına takılmayın. Siz daha açıklayıcı ve yerinde ifadeler kullanın :)

Burada ise adım adım şöyle ilerliyorum;

  • input, textarea ve button elementlerinin render olup olmadığını kontrol ediyorum. Bunları bir test scope içerisinde de yapabilirsiniz, sorun olmayacaktır. Ben biraz daha anlaşılır olmasını istediğimden dolayı ayırarak yazdım. Burada yapılan işlemler ise component'i çağır, hangi element'in render olup olmadığını kontrol etmek istiyorsun onu çağır ve toBeInTheDocument fonksiyonu ile kontrol et. Eğer render olmuyorsa zaten fail verecektir.
  • Bir diğer test case'i ise butonun disable olup olmama durumu. Butonun disable olması için input ve textarea'nın boş olması gerekiyor. O yüzden ilk aşamada bu inputların value'larını dolduruyorum. Daha sonra ise not.toBeDisabled fonksiyonu ile butonun disable olmadığını kontrol ediyorum. Burada ekstra olarak userEvent kütüphanesi ile input ve textarea'ların value'larını değiştirdim.

userEvent kütüphanesi ile input değerini girebiliyor, trigger yaratabiliyor ya da herhangi bir şey upload edebiliyorsun. Detaylı kullanım için şu sayfayı inceleyebilirsiniz.

Diğer component'i de ayrıca yazmak istemedim. Çünkü birbirine benzeyen yapı olduğu için tek component üzerinden hepsini anlatmış oldum. İncelemek isterseniz github üzerinden detaylı bir şekilde inceleyebilirsiniz.

# Şimdi sırada Integration Test

Bence tek başına unit testler yeterli olmuyor. Çünkü componentler birbirleriyle bağlantılı olabiliyor. Bu yüzden integration test ile uçtan uca bir test yazmak gerekiyor. Benim tercihim burada Cypress oluyor. Çünkü yazımı olsun, sunduğu imkanlar olsun benim için 1-0 öne geçiyor.

Gerekli kurulumları yaptıktan sonra sıra geliyor test yazmaya. Benim testimde 4 adım var. Bunlar;

  • Öncelikle testin yazılacağı adrese gidilecek. Benim örneğimde "/" olacak. (1)
  • Daha sonra input ve textarea seçilip gerekli değerleri ile doldurulacak. (2)
  • Input ve textarea'nın değerleri girildikten sonra butona tıklanacak. (3)
  • Butona tıklandıktan sonra aslında girilen veriler ekranda gözükmesi gerekiyor. Bu nokta da vermiş olduğum HTML etiketi sayesinde kontrol ediyorum. (4)
describe('first test', () => {
  it('post a comment', () => {
    cy.visit('/'); // (1)

    // inputları doldur. (2)
    cy.get('input[type="text"]').type('Berat Bozkurt');
    cy.get('textarea').type('Bu bir deneme yorumdur.');

    // butona tıkla (3)
    cy.get('button').click();

    // yorum gönderildi mi kontrol et. (4)
    cy.get('article p').invoke('text').should('eq', 'Bu bir deneme yorumdur.');
  });
});
Tüm kaynaklar ve dökümanlar yazının en altında bulunmaktadır.
  • cy.visit fonksiyonu ile adresimize gidiyoruz.
  • cy.get fonksiyonu ile elemanlarımızı seçiyoruz.
  • cy.get(XX).type fonksiyonu ile elemanların değerlerini giriyoruz.
  • cy.get(xx).click fonksiyonu ile butona tıklıyoruz.
  • cy.get(XX).invoke('text').should('eq', 'TEXT') fonksiyonu ile elemanın içerisindeki text ne ise TEXT ile yazdığımız değer ile eş değer mi onu kontrol ediyoruz. Çünkü should fonksiyonuna gönderdiğimiz ilk parametre eq.

Integration test yazma işlemini tamamladıktan sonra ister terminal istersen browser üzerinden test işlemi gerçekleşiyor. Benim tercihim browser üzerinden test işlemi gerçekleştirmek. Çünkü browser üzerinden test işlemi gerçekleştirdiğimde eğer bir hata varsa o hata ile karşılaştığım zaman hata mesajı ile karşılaşıyorum. Bu da benim için daha anlaşılır oluyor.

Sonuç

Aslında test yazmak o kadar da zor olmadığını görüyoruz. Sadece bunun için gerekli zamanı ayırıp case'leri belirlememiz gerekmektedir. Daha sonra ise daha kaliteli ve sağlam bir kod yapısı oluşturmuş oluyoruz. Çünkü case'lerimiz belli. Eğer component ileride bir revize geçirecekse bug yaratma olasılığımız çok ama çok azalıyor. Hem de test coverage ile yazdığımız component'lerin ne kadar test edildiğini görebiliyoruz. Bu da projenin kalitesini arttırıyor.


Yazıyı bitirmeden önce beni aşağıdaki sosyal medya hesaplarımdan takip edebilirsiniz. Aklınıza takılan bir şey olması halinde mesaj ya da olmasına da gerek kalmadan bir selam gönderebilirsiniz.

Kaynakça

İşte Benim için 2022

Kişisel30 Aralık 2022 4 dk okuma

Yine bir bakmışız ki bir yılın daha sonuna gelmişiz. Bugün (Cuma) izinli olduğumdan dolayı bir sevinçle her zaman olduğu gibi yine koca yılı değerlendirdiğim bir yazı yazıyorum. Ama öncesinde gelin 2021 yılı benim için nasıl geçmiş ona bir göz atalım. Hemen şuraya tıklayın ve okuyup gelin hadi ben senin için bekliyorum...

23 yıllık hayatımın belki de en yoğun, stresli ve bir o kadar yorucu geçen yılıydı. Neler oldu neler... hazırsanız gelin başlayalım hadi.

Evlendim

Yaklaşık 7 aylık bir düğün ve ev hazırlığı sürecini atlatıp evlendim. Saç beyazlaması ve kilo kayıpları ile geçen bu günler yerini rahatlığa ve huzurluğa bıraktı. Dönüp geriye baktığımda aklıma gelen şeylerin başında stres, yorgunluk ve borç :)

Yeni eve taşındım

Üniversiteye kadar hep aile evindeydim. Üniversiteye geçtikten sonra 2 sene yurtta kaldım. Zaten sonra da pandemi patlak verince eve geçtik ve aile ile yaşamaya devam. Ta ki evlenene kadar. Evlendikten sonra Sakarya'ya taşındım ve ilk defa eve çıktım. Bilmediğim bir şehirde, bilmediğim bir mahallede yeni bir hayat kurmak... Tıpkı her şeye tekrardan başlamak gibi.

Yeni çalışma ortamım
Yeni çalışma ortamım

Yeni eve geçtikten sonra da kendime yeni bir çalışma ortamı yarattım. Şu an en sade şekilde hazır. Zamanla yeni ekipmanlar ve oyuncaklarla zenginleştirmeyi planlıyorum. Şimdilik bu kadar işimi fazlasıyla görüyor.

İngilizcemi geliştirdim

Gerek ingilizce makaleler okuyarak gerekse ingilizce videolar izleyerek ingilizcemi geliştirdiğimi söyleyebilirim. Ama en çok iş hayatımda yoğun ve aktif bir şekilde kullandığımdan dolayı gelişimin daha fazla olduğunu rahat bir şekilde söyleyebilirim. Tabii asla ama asla tam olmayacağım bunun için kelime ezberleme süreçlerine ağırlık vermem gerektiğini de biliyorum. Hatta bununla ilgili bir side proje geliyor ama şimdilik sır :)

Blogumu geliştirdim

Blogumu yepyeni bir görünümle tekrardan geliştirdim ve yayına aldım. Burayı daha çok günlük/not defteri gibi davranıp yeni özellikler ekleyip geliştirmeye de devam ediyorum. Burası adeta arka bahçemmiş gibi davranıp yeni teknolojiler, özellikler deneyip duruyorum. Bu şekilde güncel kalmak gerçekten hoşuma gidiyor.

Blogtaki bir özellik
Blogtaki bir özellik

Belki de farketmemişsinizdir diye kısaca birkaç sayfamdan ve yazımdan bahsetmek isterim;

  • İnternette gezinirken hoşuma giden ilgimi çeken web sayfalarını kaydediyorum ve kaydettiklerimi de Yer imleri sayfasında paylaşıyorum.
  • Fotoğraflara karşı da ayrı bir ilgim olduğu için çektiğim fotoğrafları Fotoğraflar sayfası altında paylaşıyorum.
  • Hayatımda olan özel anları ise Journey sayfasında paylaşıyorum. Bu şekilde dönüp baktığımda bazı tarihleri kolay bir şekilde hatırlıyor ve gözümün önüne getirebiliyorum. Unutkan olmak kötü bir şey arkadaşlar...
  • Aktif olarak kullandığım uygulamaları paylaştığım bir sayfa yayımlamıştım. Merak mı ettiniz? Neler kullanıyorum? sayfasına bakabilirsiniz.

Side projeler geliştirmeye başladım

Boşa kalan vakitlerimde belki bir ek gelir olur diye birkaç uygulama yapıp yayınlamak istiyorum. Buradaki kazanç sağlama düşüncelerimin başında ilk olarak reklam geliri, bir diğeri destek geliri, son olarak da emin değilim ama uygulama içi ücretli özellikler olabilir. Şu an halı hazırda üzerinde çalıştığım iki projem var. Her iki proje de mobil platformlar ve chrome extension şeklinde paylaşacağım.

Aeropress ile kahve yapmaya başladım

Çalışırken kahve içmeyi seviyorum. Normalde Nescafe 3'ü 1 arada yaparak içerim ama biraz heyecan olsun diye Aeropress ile kahve yapmaya başladım. Sert bir kahve içmeyi sevmiyorum açıkcası. Süt ile karıştırıp içiyorum. Bazen mocha bazen de caramel latte yaparak içiyorum.

Caramel latte
Caramel latte

Yeni fotoğraflar çektim

Fotoğrafçılık aslında her an yanımda olan bir hobi. Gözüme güzel bir şey gelirse telefonu çıkarıp hemen çekerim. Boş bir vaktimde ise Lightroom ile düzenleyip mutlaka paylaşırım. Bu süreç gerçekten beni dinlendiriyor ve huzur veriyor, tatmin ediyor.

Çektiğim fotoğraflarÇektiğim fotoğraflarÇektiğim fotoğraflarÇektiğim fotoğraflarÇektiğim fotoğraflarÇektiğim fotoğraflar
Çektiğim fotoğraflar

Acısıyla tatlısıyla geçen 365 gün. Bambaşka hayaller, yepyeni umutlar ile yeni yıla birkaç gün kaldı. Kalın sağlıcakla!

MacOS'ta Birden Fazla Github Hesabı Nasıl Kullanılır?

Teknik07 Ekim 2022 2 dk okuma

Eğer sizde benim gibi bilgisayarınızda birden fazla github hesabı kullananlardansınız problem yaşamışsınızdır. Sürekli hesap değiştirmek, config ayarlamak... Bir süre sonra insanı darlamakta. O yüzden bugün uyguladığım bir çözümü sizlerle de paylaşmak istedim.

Not: Bu anlattıklarım MacOS işletim sistemi için geçerlidir.

1. SSH Key Oluşturalım

# öncellikle ssh dizinine gidiyoruz
cd ~/.ssh  

# burada kisisel mail adresinizi ve dosya adını giriyorsunuz
ssh-keygen -t rsa -C "[email protected]" -f "kisisel-github" 

# burada iş mail adresinizi ve dosya adını giriyorsunuz
ssh-keygen -t rsa -C "[email protected]" -f "is-github" 

2. SSH Key'leri Bilgisayarımıza Kaydedelim

# burada kisisel github hesabınızın ssh key'ini ekliyoruz
ssh-add -K ~/.ssh/kisisel-github

# burada iş github hesabınızın ssh key'ini ekliyoruz
ssh-add -K ~/.ssh/is-github 

3. SSH Key'leri Github Hesaplarımıza Ekleyelim

### ssh keyimizi kopyalayıp kişisel github hesabımıza kayıt edelim.
pbcopy < ~/.ssh/kisisel-github.pub

Burada kopyalanmış olan kodu Github ayarlarından yeni SSH ekle deyip bu kodu kaydedelim. Aynı işlemi bir sonraki adım için de uygulayın.

### ssh keyimizi kopyalayıp iş github hesabımıza kayıt edelim.
pbcopy < ~/.ssh/is-github.pub

4. Config Dosyasını Oluşturalım

# config dosyasını oluşturalım ve düzenleyelim.
touch ~/.ssh/config
open -e ~/.ssh/config

Açılan pencerede şu yapılandırmaları ekleyelim.

#kişisel
Host kisisel-github.com
	HostName github.com
	User git
	IdentityFile ~/.ssh/kisisel-github

#iş
Host is-github.com
	HostName github.com
	User git
	IdentityFile ~/.ssh/is-github

5. İş Projelerine Özel Config Oluşturalım

İş ile ilgili projelerimizde özel bir config dosyası oluşturmamız gerekiyor. Bunun için iş ile ilgili olanların hepsini bir klasörde tutup oradan config dosyasını çekeceğiz. Bu şekilde iş klasörüne geçince farklı git bilgileri, kişisel projelerinize geçince de farklı bir git hesabı ile çalışmış olacaksınız. Bu şekilde aslında bölünmeden sağlıklı bir şekilde iş ve kişisel hesaplarınızı kullanabilirsiniz.

# iş klasörünüze gidin ve .gitconfig oluşturun
touch ~/work/.gitconfig
open -e ~/work/.gitconfig

Şimdi içerisine şu yapılandırmaları ekleyelim.

[user]
    name = Berat Bozkurt
    email = [email protected]

Şimdi son adım olarak ana .gitconfig dosyamıza iş klasöründe oluşturduğumuz yapılandırmaları dahil edelim. Bunun için şu yapılandırmayı eklemeniz yeterlidir.

# ana .gitconfig dosyasını açalım.
open -e ~/.gitconfig

# açılan pencerede bu yapılandırmaları ekleyelim.
[user]
    name = Berat Bozkurt
    email = [email protected]
[includeIf "gitdir:~/works/"]
    path = ~/works/.gitconfig

Arkanıza yaslanın ve kodunuza bakın. Sürekli hesap değiştirmekle, giriş yapmakla uğraşmayın. Keyifle kodlayınız...

Sevgiler.

Referanslar:

Diğer yazılara göz at!

# Son Fotoğraflar

Two people in train
Diğer fotoğraflara göz at!