Wraps Memcached cache testing against a real container: an inline set/get/expire/no-persistence worked example, with the exhaustive protocol-command tests (set/get/add/cas/incr/decr, TTL 0=never-expire / 30-day Unix-timestamp boundary) and the LRU-eviction, consistent-hashing distribution, ElastiCache Auto Discovery, and CI-wiring deep-dives in references/. Use when writing tests for an application that uses Memcached as its primary cache, when verifying ElastiCache Memcached cluster behaviour, or when contrasting Memcached eviction and distribution semantics against Redis.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Memcached is a widely deployed in-memory cache, available as the ElastiCache Memcached tier on AWS. It differs from Redis in three fundamental ways that affect how tests must be written:
This skill wraps test patterns against a real Memcached instance via Testcontainers - not a mock. Mocks lose LRU eviction, TTL-tick, and consistent-hashing redistribution behaviour that real bugs hide in.
pip install pymemcache testcontainers # Python
npm install --save-dev memjs testcontainers # Node (binary protocol)The Testcontainers Memcached module defaults to memcached:1 and exposes
port 11211
(testcontainers-python memcached):
from testcontainers.memcached import MemcachedContainer
with MemcachedContainer("memcached:1.6-alpine") as mc:
host, port = mc.get_host_and_port()import pytest
from pymemcache.client.base import Client
from testcontainers.memcached import MemcachedContainer
@pytest.fixture(scope="session")
def mc_addr():
with MemcachedContainer("memcached:1.6-alpine") as mc:
yield mc.get_host_and_port() # (host, port)
@pytest.fixture
def mc(mc_addr):
host, port = mc_addr
client = Client((host, port), default_value=None)
yield client
client.flush_all() # Reset between testsAssert the four signature Memcached behaviours in one pass against the mc
fixture - a value round-trips, add is refused on an existing key, a short
TTL evicts by expiry, and nothing survives a flush (the no-persistence
guarantee, modelling a node restart):
import time
def test_memcached_end_to_end(mc):
# 1. set then get - the value round-trips
mc.set("session:42", b"active")
assert mc.get("session:42") == b"active"
# 2. add is refused when the key already exists
assert mc.add("session:42", b"other") is False
# 3. a 1 s TTL expires the key (evict-by-expiry)
mc.set("otp:42", b"123456", expire=1)
assert mc.get("otp:42") == b"123456"
time.sleep(1.5)
assert mc.get("otp:42") is None
# 4. no persistence - flush models a node restart; data is gone
mc.flush_all()
assert mc.get("session:42") is NoneRun it:
pytest tests/memcached/ -vThat is the whole loop - container up, real client, assert a real cache behaviour, tear down. From here, expand into the full command matrix and the cluster-level tests via the two references linked in How to use.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Mocking the Memcached client | Misses TTL-tick, LRU eviction, CAS token generation | Use Testcontainers / real Memcached |
time.sleep(60) to test TTL | Slow and flaky | Set 1 s TTL and sleep 1.5 s |
Asserting incr initialises a missing key | incr returns None on missing keys | Use add to initialise, then incr |
| Sharing a Memcached instance between test suites | Cross-suite key pollution, order-dependent failures | flush_all in fixture teardown |
| Expecting data after a Memcached restart | Memcached has no persistence | Test for graceful cache-miss handling |
| Using a single-node client to test distribution | Distribution logic never exercises consistent hashing | Use HashClient with two test containers |
| Hard-coding node endpoints in app code | Breaks on ElastiCache node replacement | Use the configuration endpoint + Auto Discovery |
noreply=True in set during assertion tests | Errors are silently swallowed | Set noreply=False (pymemcache default for development) |
scope="session" fixtures and flush_all between tests.mg/ms) is available in Memcached 1.6+ and
offers stampede-handling flags (W/Z) and atomic CAS overrides, but
requires a client library with meta-protocol support; not covered by
pymemcache 4.x defaults.add for counters, incr/decr):
github.com/memcached/memcached/wiki/Programming.redis-cache-tests,
cache-coherence-patterns-reference,
cache-stampede-reference.