diff --git a/tests/scrapers/conftest.py b/tests/scrapers/conftest.py
new file mode 100644
index 0000000..3248ec2
--- /dev/null
+++ b/tests/scrapers/conftest.py
@@ -0,0 +1,41 @@
+import pytest
+
+
+@pytest.fixture
+def mock_codeforces_html():
+ return """
+
+
+ """
+
+
+@pytest.fixture
+def mock_atcoder_html():
+ return """
+ Sample Input 1
+ 3
+1 2 3
+ Sample Output 1
+ 6
+ """
+
+
+@pytest.fixture
+def mock_cses_html():
+ return """
+ Example
+ Input:
+ 3
+1 2 3
+ Output:
+ 6
+ """
diff --git a/tests/scrapers/test_atcoder.py b/tests/scrapers/test_atcoder.py
new file mode 100644
index 0000000..5086894
--- /dev/null
+++ b/tests/scrapers/test_atcoder.py
@@ -0,0 +1,50 @@
+from unittest.mock import Mock
+from scrapers.atcoder import scrape, scrape_contest_problems
+
+
+def test_scrape_success(mocker, mock_atcoder_html):
+ mock_response = Mock()
+ mock_response.text = mock_atcoder_html
+
+ mocker.patch("scrapers.atcoder.requests.get", return_value=mock_response)
+
+ result = scrape("https://atcoder.jp/contests/abc350/tasks/abc350_a")
+
+ assert len(result) == 1
+ assert result[0][0] == "3\n1 2 3"
+ assert result[0][1] == "6"
+
+
+def test_scrape_contest_problems(mocker):
+ mock_response = Mock()
+ mock_response.text = """
+
+ """
+
+ mocker.patch("scrapers.atcoder.requests.get", return_value=mock_response)
+
+ result = scrape_contest_problems("abc350")
+
+ assert len(result) == 2
+ assert result[0] == {"id": "a", "name": "A - Water Tank"}
+ assert result[1] == {"id": "b", "name": "B - Dentist Aoki"}
+
+
+def test_scrape_network_error(mocker):
+ mocker.patch(
+ "scrapers.atcoder.requests.get", side_effect=Exception("Network error")
+ )
+
+ result = scrape("https://atcoder.jp/contests/abc350/tasks/abc350_a")
+
+ assert result == []
diff --git a/tests/scrapers/test_codeforces.py b/tests/scrapers/test_codeforces.py
new file mode 100644
index 0000000..67277ea
--- /dev/null
+++ b/tests/scrapers/test_codeforces.py
@@ -0,0 +1,53 @@
+from unittest.mock import Mock
+from scrapers.codeforces import scrape, scrape_contest_problems
+from scrapers.models import Problem
+
+
+def test_scrape_success(mocker, mock_codeforces_html):
+ mock_scraper = Mock()
+ mock_response = Mock()
+ mock_response.text = mock_codeforces_html
+ mock_scraper.get.return_value = mock_response
+
+ mocker.patch(
+ "scrapers.codeforces.cloudscraper.create_scraper", return_value=mock_scraper
+ )
+
+ result = scrape("https://codeforces.com/contest/1900/problem/A")
+
+ assert len(result) == 1
+ assert result[0].input == "1\n3\n1 2 3"
+ assert result[0].expected == "6"
+
+
+def test_scrape_contest_problems(mocker):
+ mock_scraper = Mock()
+ mock_response = Mock()
+ mock_response.text = """
+ A. Problem A
+ B. Problem B
+ """
+ mock_scraper.get.return_value = mock_response
+
+ mocker.patch(
+ "scrapers.codeforces.cloudscraper.create_scraper", return_value=mock_scraper
+ )
+
+ result = scrape_contest_problems("1900")
+
+ assert len(result) == 2
+ assert result[0] == Problem(id="a", name="A. Problem A")
+ assert result[1] == Problem(id="b", name="B. Problem B")
+
+
+def test_scrape_network_error(mocker):
+ mock_scraper = Mock()
+ mock_scraper.get.side_effect = Exception("Network error")
+
+ mocker.patch(
+ "scrapers.codeforces.cloudscraper.create_scraper", return_value=mock_scraper
+ )
+
+ result = scrape("https://codeforces.com/contest/1900/problem/A")
+
+ assert result == []
diff --git a/tests/scrapers/test_cses.py b/tests/scrapers/test_cses.py
new file mode 100644
index 0000000..1dd0096
--- /dev/null
+++ b/tests/scrapers/test_cses.py
@@ -0,0 +1,46 @@
+from unittest.mock import Mock
+from scrapers.cses import scrape, scrape_all_problems
+
+
+def test_scrape_success(mocker, mock_cses_html):
+ mock_response = Mock()
+ mock_response.text = mock_cses_html
+
+ mocker.patch("scrapers.cses.requests.get", return_value=mock_response)
+
+ result = scrape("https://cses.fi/problemset/task/1068")
+
+ assert len(result) == 1
+ assert result[0][0] == "3\n1 2 3"
+ assert result[0][1] == "6"
+
+
+def test_scrape_all_problems(mocker):
+ mock_response = Mock()
+ mock_response.text = """
+ Introductory Problems
+ Weird Algorithm
+ Missing Number
+ Sorting and Searching
+ Apartments
+ """
+
+ mocker.patch("scrapers.cses.requests.get", return_value=mock_response)
+
+ result = scrape_all_problems()
+
+ assert "Introductory Problems" in result
+ assert "Sorting and Searching" in result
+ assert len(result["Introductory Problems"]) == 2
+ assert result["Introductory Problems"][0] == {
+ "id": "1068",
+ "name": "Weird Algorithm",
+ }
+
+
+def test_scrape_network_error(mocker):
+ mocker.patch("scrapers.cses.requests.get", side_effect=Exception("Network error"))
+
+ result = scrape("https://cses.fi/problemset/task/1068")
+
+ assert result == []